Testing And Benchmarking in Squirrel

Here’s an idiomatic Squirrel example demonstrating testing and benchmarking:

// IntMin.nut

function IntMin(a, b) {
    return a < b ? a : b;
}

// Test.nut

class Test {
    constructor() {
        this.failures = 0;
    }

    function assert(condition, message) {
        if (!condition) {
            print("FAIL: " + message);
            this.failures++;
        }
    }

    function run() {
        this.testIntMinBasic();
        this.testIntMinTableDriven();
        
        if (this.failures == 0) {
            print("All tests passed!");
        } else {
            print(format("%d test(s) failed.", this.failures));
        }
    }

    function testIntMinBasic() {
        local ans = IntMin(2, -2);
        this.assert(ans == -2, "IntMin(2, -2) = " + ans + "; want -2");
    }

    function testIntMinTableDriven() {
        local tests = [
            { a = 0, b = 1, want = 0 },
            { a = 1, b = 0, want = 0 },
            { a = 2, b = -2, want = -2 },
            { a = 0, b = -1, want = -1 },
            { a = -1, b = 0, want = -1 },
        ];

        foreach (idx, tt in tests) {
            local ans = IntMin(tt.a, tt.b);
            this.assert(ans == tt.want, format("Test case %d: IntMin(%d, %d) = %d; want %d", 
                idx, tt.a, tt.b, ans, tt.want));
        }
    }
}

// Benchmark.nut

class Benchmark {
    constructor(iterations) {
        this.iterations = iterations;
    }

    function run() {
        local startTime = time();
        
        for (local i = 0; i < this.iterations; i++) {
            IntMin(1, 2);
        }
        
        local endTime = time();
        local duration = endTime - startTime;
        
        print(format("Benchmark completed %d iterations in %.6f seconds", 
            this.iterations, duration));
        print(format("Average time per operation: %.9f seconds", 
            duration.tofloat() / this.iterations));
    }
}

// Main.nut

dofile("IntMin.nut");
dofile("Test.nut");
dofile("Benchmark.nut");

print("Running tests...");
Test().run();

print("\nRunning benchmark...");
Benchmark(1000000).run();

This Squirrel code demonstrates testing and benchmarking concepts similar to the Go example. Here’s an explanation of the code:

  1. We define the IntMin function in a separate file (IntMin.nut) for testing.

  2. The Test class provides a simple testing framework:

    • assert method for checking conditions
    • run method to execute all tests
    • Individual test methods (testIntMinBasic and testIntMinTableDriven)
  3. The Benchmark class allows us to measure the performance of the IntMin function:

    • It runs the function a specified number of times
    • Calculates and reports the total time and average time per operation
  4. In the main script, we:

    • Load the necessary files using dofile
    • Run the tests
    • Run the benchmark

To run this code:

  1. Save each part (IntMin, Test, Benchmark, and Main) in separate .nut files.
  2. Run the main script using the Squirrel interpreter:
$ sq Main.nut

This will execute the tests and benchmark, providing output similar to:

Running tests...
All tests passed!

Running benchmark...
Benchmark completed 1000000 iterations in 0.123456 seconds
Average time per operation: 0.000000123 seconds

Note that Squirrel doesn’t have built-in testing or benchmarking libraries like Go does. This example provides a simple implementation to demonstrate the concepts. In a real-world scenario, you might want to use or create more robust testing and benchmarking utilities for Squirrel.