|
@@ -1,10 +1,112 @@
|
|
|
+//
|
|
|
+// A big advantage of Zig is the integration of its own test system.
|
|
|
+// This allows the philosophy of Test Driven Development (TDD) to be
|
|
|
+// implemented perfectly. Zig even goes one step further than other
|
|
|
+// languages, the tests can be included directly in the source file.
|
|
|
+//
|
|
|
+// This has several advantages. On the one hand it is much clearer to
|
|
|
+// have everything in one file, both the source code and the associated
|
|
|
+// test code. On the other hand, it is much easier for third parties
|
|
|
+// to understand what exactly a function is supposed to do if they can
|
|
|
+// simply look at the test inside the source and compare both.
|
|
|
+//
|
|
|
+// Especially if you want to understand how e.g. the standard library
|
|
|
+// of Zig works, this approach is very helpful. Furthermore it is very
|
|
|
+// practical, if you want to report a bug to the Zig community, to
|
|
|
+// illustrate it with a small example including a test.
|
|
|
+//
|
|
|
+// Therefore, in this exercise we will deal with the basics of testing
|
|
|
+// in Zig. Basically, tests work as follows: you pass certain parameters
|
|
|
+// to a function, for which you get a return - the result. This is then
|
|
|
+// compared with the EXPECTED value. If both values match, the test is
|
|
|
+// passed, otherwise an error message is displayed.
|
|
|
+//
|
|
|
+// testing.expect(foo(param1, param2) == expected);
|
|
|
+//
|
|
|
+// Also other comparisons are possible, deviations or also errors can
|
|
|
+// be provoked, which must lead to an appropriate behavior of the
|
|
|
+// function, so that the test is passed.
|
|
|
+//
|
|
|
+// Tests can be run via Zig build system or applied directly to
|
|
|
+// individual modules using "zig test xyz.zig".
|
|
|
+//
|
|
|
+// Both can be used script-driven to execute tests automatically, e.g.
|
|
|
+// after checking into a Git repository. Something we also make extensive
|
|
|
+// use of here at Ziglings.
|
|
|
+//
|
|
|
const std = @import("std");
|
|
|
const testing = std.testing;
|
|
|
|
|
|
-fn add(a: u16, b: u16) u16 {
|
|
|
+// This is a simple function
|
|
|
+// that builds a sum from the
|
|
|
+// passed parameters and returns.
|
|
|
+fn add(a: f16, b: f16) f16 {
|
|
|
return a + b;
|
|
|
}
|
|
|
|
|
|
-test "simple test" {
|
|
|
+// The associated test.
|
|
|
+// It always starts with the keyword "test",
|
|
|
+// followed by a description of the tasks
|
|
|
+// of the test. This is followed by the
|
|
|
+// test cases in curly brackets.
|
|
|
+test "add" {
|
|
|
+
|
|
|
+ // The first test checks if the sum
|
|
|
+ // of '41' and '1' gives '42', which
|
|
|
+ // is correct.
|
|
|
try testing.expect(add(41, 1) == 42);
|
|
|
+
|
|
|
+ // Another way to perform this test
|
|
|
+ // is as follows:
|
|
|
+ try testing.expectEqual(add(41, 1), 42);
|
|
|
+
|
|
|
+ // This time a test with the addition
|
|
|
+ // of a negative number:
|
|
|
+ try testing.expect(add(5, -4) == 1);
|
|
|
+
|
|
|
+ // And a floating point operation:
|
|
|
+ try testing.expect(add(1.5, 1.5) == 3);
|
|
|
+}
|
|
|
+
|
|
|
+// Another simple function
|
|
|
+// that returns the result
|
|
|
+// of subtracting the two
|
|
|
+// parameters.
|
|
|
+fn sub(a: f16, b: f16) f16 {
|
|
|
+ return a - b;
|
|
|
+}
|
|
|
+
|
|
|
+// The corresponding test
|
|
|
+// is not much different
|
|
|
+// from the previous one.
|
|
|
+// Except that it contains
|
|
|
+// an error that you need
|
|
|
+// to correct.
|
|
|
+test "sub" {
|
|
|
+ try testing.expect(sub(10, 5) == 6);
|
|
|
+
|
|
|
+ try testing.expect(sub(3, 1.5) == 1.5);
|
|
|
+}
|
|
|
+
|
|
|
+// This function divides the
|
|
|
+// numerator by the denominator.
|
|
|
+// Here it is important that the
|
|
|
+// denominator must not be zero.
|
|
|
+// This is checked and if it
|
|
|
+// occurs an error is returned.
|
|
|
+fn divide(a: f16, b: f16) !f16 {
|
|
|
+ if (b == 0) return error.DivisionByZero;
|
|
|
+ return a / b;
|
|
|
+}
|
|
|
+
|
|
|
+test "divide" {
|
|
|
+ try testing.expect(divide(2, 2) catch unreachable == 1);
|
|
|
+ try testing.expect(divide(-1, -1) catch unreachable == 1);
|
|
|
+ try testing.expect(divide(10, 2) catch unreachable == 5);
|
|
|
+ try testing.expect(divide(1, 3) catch unreachable == 0.3333333333333333);
|
|
|
+
|
|
|
+ // Now we test if the function returns an error
|
|
|
+ // if we pass a zero as denominator.
|
|
|
+ // But which error needs to be tested?
|
|
|
+ try testing.expectError(error.???, divide(15, 0));
|
|
|
}
|