?? Testing Tutorial

Learn how to write effective tests for your Ifá-Lang programs.

Assertions with ?`w?`

The ?`w?` (or English alias verify) statement asserts conditions at runtime:

// Basic assertions
?`w?` 2 + 2 == 4              // Passes
?`w?` Ika.len("hello") == 5   // Passes

// With custom message
?`w?` user != nil, "User must exist"

// English alias
verify total > 0, "Total must be positive"

Test Functions

Organize tests in functions with the test_ prefix:

// test_math.ifa

ise test_addition() {
    ?`w?` 2 + 2 == 4;
    ?`w?` -1 + 1 == 0;
    ?`w?` 0.1 + 0.2 == 0.3;  // Note: float precision!
    Irosu.fo("? test_addition passed");
}

ise test_subtraction() {
    ?`w?` 5 - 3 == 2;
    ?`w?` 0 - 1 == -1;
    Irosu.fo("? test_subtraction passed");
}

// Run all tests
test_addition();
test_subtraction();
Irosu.fo("All tests passed!");

Running Tests

# Run a single test file
ifa run tests/test_math.ifa

# Run all tests in directory
ifa test tests/

# Run with verbose output
ifa test --verbose tests/

Testing Errors

Test that code properly handles errors:

ise test_error_handling() {
    // Test that division by zero returns error
    ayanmo result = Okanran.try(|| {
        padap? 10 / 0;
    });
    
    ?`w?` Okanran.is_error(result), "Division by zero should error";
    
    // Test error message
    ayanmo msg = Okanran.message(result);
    ?`w?` Ika.contains(msg, "division"), "Should mention division";
    
    Irosu.fo("? test_error_handling passed");
}

Test Fixtures

Set up test data before tests:

ise setup_test_data() {
    padap? {
        "users": [
            {"id": 1, "name": "Alice"},
            {"id": 2, "name": "Bob"}
        ],
        "products": [
            {"sku": "A001", "price": 100}
        ]
    };
}

ise test_user_lookup() {
    ayanmo data = setup_test_data();
    ayanmo user = Ogunda.find(data["users"], |u| u["id"] == 1);
    
    ?`w?` user != nil;
    ?`w?` user["name"] == "Alice";
}

Testing File I/O

ise test_file_operations() {
    ayanmo test_file = "test_output.txt";
    
    // Write
    Odi.write(test_file, "Hello, World!");
    ?`w?` Odi.exists(test_file);
    
    // Read
    ayanmo content = Odi.read(test_file);
    ?`w?` content == "Hello, World!";
    
    // Cleanup
    Odi.delete(test_file);
    ?`w?` !Odi.exists(test_file);
    
    Irosu.fo("? test_file_operations passed");
}

Mocking Network Calls

// Create a mock HTTP client
ayanmo mock_responses = {};

ise mock_get(url) {
    ti (mock_responses[url] != nil) {
        padap? mock_responses[url];
    }
    padap? Okanran.error("Unmocked URL: " + url);
}

ise test_api_client() {
    // Set up mock
    mock_responses["https://api.example.com/users"] = {
        "status": 200,
        "body": "[{\"id\": 1}]"
    };
    
    // Test with mock
    ayanmo response = mock_get("https://api.example.com/users");
    ?`w?` response["status"] == 200;
}

Best Practices