DEV Community

Sergio Marcial
Sergio Marcial

Posted on

🚀🧪Unlocking the Power of Approval Testing 🔥💻

Testing is the backbone of software development, ensuring the reliability and quality of our code. But when it comes to testing complex and ever-evolving software, traditional methods often fall short. That's where Approval Testing steps in—a revolutionary (but not new) approach that simplifies complex scenarios, embraces change, and helps you write more robust software. In this guide, we'll dive into the world of Approval Testing, understanding its fundamentals, its niche in software engineering, and how it differs from other testing methodologies. With code examples in some languages.

Table of Contents:

  1. What is Approval Testing?
  2. The Core Principles
  3. Practical Application
  4. The Niche Approval Testing Addresses
  5. Key Benefits
  6. Key Differences Between Approval Testing and Other Testing Methods
  7. Code Examples in Different Languages
  8. Real-World Use Cases
  9. Real-World Examples
  10. Choosing the Right Tool
  11. Conclusion

1. What is Approval Testing?

Approval Testing is a testing methodology that focuses on capturing the current output of a piece of code and then comparing it to a previously approved version. Instead of requiring developers to predict the exact output, Approval Testing encourages them to approve the current output as correct and uses it as a reference for future testing.

2. The Core Principles

To grasp the essence of Approval Testing, it's essential to understand its core principles:

No Predictions: Unlike traditional unit tests that require developers to predict the exact output, Approval Testing captures and approves the current output. This makes it suitable for scenarios where predictions are challenging.

Change Embrace: In agile development environments where change is constant, Approval Testing shines. It accommodates evolving codebases and minimizes the need for frequent test updates.

Versatility: Approval Testing isn't limited to a specific type of output. It can be applied to databases, APIs, GUIs, and any scenario involving textual or binary output.

3. Practical Application

Let's delve into a practical example to see how Approval Testing works in action. Suppose we have a function calculate_total_price that calculates the total price of items in a shopping cart:

def calculate_total_price(cart):
    total_price = sum(item.price for item in cart)
    return f'Total Price: ${total_price:.2f}'
Enter fullscreen mode Exit fullscreen mode

With Approval Testing, we capture the current output:

from approvaltests.approvals import verify

cart = [Item("Item A", 10.99), Item("Item B", 7.50)]
result = calculate_total_price(cart)
verify(result)
Enter fullscreen mode Exit fullscreen mode

4. The Niche Approval Testing Addresses

Approval Testing is designed to tackle specific challenges encountered by software engineers:

  • Complex Output: In scenarios where the output is complex or includes non-deterministic elements (e.g., timestamps), predicting exact values for unit tests can be daunting. Approval Testing eliminates the need for such predictions.

  • Evolving Codebases: Agile development environments thrive on change. Frequent code updates can cause traditional unit tests to break. Approval Testing embraces evolving codebases and adapts seamlessly.

  • Non-Visual Output: Unlike some testing methods that are primarily visual, Approval Testing is versatile. It can be employed for databases, APIs, and any scenario where textual or binary output is involved.

5. Key Benefits

Approval Testing offers several key benefits:

Simplified Testing: Approval Testing simplifies complex testing scenarios, especially when predicting exact outputs is challenging.

Adaptability: It adapts seamlessly to evolving codebases, reducing the need for frequent test updates.

Accurate Documentation: The approved output serves as documentation, allowing developers to understand the expected behavior easily.

6. Key Differences Between Approval Testing and Other Testing Methods

To appreciate Approval Testing fully, let's draw comparisons with other popular testing methods:

  • Unit Testing: Unit tests require developers to specify expected outcomes. Approval Testing, on the other hand, captures actual outcomes and uses them as references. This makes it especially effective for scenarios where predicting outcomes is challenging.

  • Integration Testing: Integration tests focus on interactions between components. While Approval Testing is not a replacement for integration tests, it can complement them by validating non-deterministic behavior within the integration.

  • Property-Based Testing: Property-based testing generates a large number of inputs to test code. Approval Testing doesn't generate inputs; instead, it captures and verifies outputs. This makes it suitable for scenarios where you're concerned with the correctness of outputs rather than input generation.

7. Code Examples in Different Languages

Let's explore Approval Testing through practical code examples in three popular programming languages: Python, Java, and JavaScript.

Python Example:

import unittest
from approvaltests.approvals import verify

def add_numbers(a, b):
    return a + b

class TestAddition(unittest.TestCase):
    def test_addition(self):
        result = add_numbers(2, 3)
        verify(result)
Enter fullscreen mode Exit fullscreen mode

Java Example:

import org.junit.jupiter.api.Test;
import org.approvaltests.combinations.CombinationApprovals;

class CombinationTest {
    @Test
    void testCombination() {
        CombinationApprovals.verifyAllCombinations(
            (a, b) -> calculate(a, b),
            new int[]{1, 2, 3},
            new int[]{10, 20, 30}
        );
    }

    int calculate(int a, int b) {
        return a + b;
    }
}
Enter fullscreen mode Exit fullscreen mode

JavaScript Example:

const { verify } = require('approvaltests');

function multiplyNumbers(a, b) {
    return a * b;
}

test('Multiplication Test', () => {
    const result = multiplyNumbers(5, 4);
    verify(result);
});
Enter fullscreen mode Exit fullscreen mode

8. Real-World Use Cases

Approval Testing finds its application in a wide array of real-world scenarios. Some examples include:

  • Validating database migrations and ensuring schema compatibility.
  • Testing APIs and confirming the correctness of responses.
  • Verifying output in financial systems, where precision matters.
  • Ensuring consistent behavior in game development, where randomness is a factor.

9. Real-World Examples

Approval Testing finds application in a wide range of real-world scenarios:

Database Schema Validation: It ensures that database migrations maintain schema compatibility.

API Testing: Approval Testing validates the correctness of API responses.

Financial Systems: In financial systems where precision is crucial, Approval Testing guarantees accurate results.

Game Development: It's used to ensure consistent behavior in games, especially when randomness is involved.

10. Choosing the Right Tool

Selecting the right tool for Approval Testing is essential. Popular tools include ApprovalTests (for various languages), TextTest (for text-based approval), and others tailored to specific scenarios.

11. Conclusion 💪

Approval Testing is not just a testing methodology; it's a mindset shift. By embracing the power of Approval Testing, you can simplify testing scenarios, adapt to evolving codebases, and ensure the correctness of your software outputs. It's a versatile tool that can make your testing efforts more robust and resilient.

As you embark on your testing journey, consider integrating Approval Testing into your testing suite. It's a valuable addition that can help you write better code, reduce bugs, and improve the overall quality of your software.

Happy testing! 🚀🧪

Top comments (2)

Collapse
 
gravy profile image
Grace Icay

Thanks for sharing your insights with this article! It's my first time hearing about Approval Testing so I checked out the tool you recommended and it's awesome that it supports most programming languages.
For those who are curious, it's open source as well: github.com/approvals/Approvals.NodeJS

Collapse
 
jkborys profile image
John Borys
  • I would like to see some real-world examples of Approval testing for Java Rest APIs.
  • I would like to see how Approval Testing can work when used on real Java Custom Classes, not just Strings.

Where might I be able to find some examples of these practical applications?