nitunit manual: document NIT_TESTING, SRAND and NIT_TESTING_ID
[nit.git] / share / man / nitunit.md
index b43004f..e80e80e 100644 (file)
@@ -1,5 +1,3 @@
-% NITUNIT(1)
-
 # NAME
 
 nitunit - executes the unit tests from Nit source files.
@@ -32,24 +30,28 @@ The execution can be verified using `assert`.
 
 Example with a class:
 
-    module foo
-    #    var foo = new Foo
-    #    assert foo.bar == 10
-    class Foo
-        var bar = 10
-    end
+~~~
+module foo
+#    var foo = new Foo
+#    assert foo.bar == 10
+class Foo
+    var bar = 10
+end
+~~~
 
 Everything used in the test must be declared.
 To test a method you have to instantiate its class:
 
-    module foo
+~~~
+module foo
+#    var foo = new Foo
+#    assert foo.bar == 10
+class Foo
     #    var foo = new Foo
-    #    assert foo.bar == 10
-    class Foo
-        #    var foo = new Foo
-        #    assert foo.baz(1, 2) == 3
-        fun baz(a, b: Int) do return a + b
-    end
+    #    assert foo.baz(1, 2) == 3
+    fun baz(a, b: Int) do return a + b
+end
+~~~
 
 In a single piece of documentation, each docunit is considered a part of a single module, thus regrouped when
 tested.
@@ -116,6 +118,15 @@ Finally, standard markdown documents can be checked with:
 
     $ nitunit foo.md
 
+When testing, the environment variable `NIT_TESTING` is set to `true`.
+This flag can be used by libraries and program to prevent (or limit) the execution of dangerous pieces of code.
+
+~~~~~
+# NIT_TESTING is automatically set.
+#
+#     assert "NIT_TESTING".environ == "true"
+~~~~
+
 ## Working with `TestSuites`
 
 TestSuites are Nit files that define a set of TestCases for a particular module.
@@ -125,16 +136,18 @@ So for the module `foo.nit` the test suite will be called `test_foo.nit`.
 
 The structure of a test suite is the following:
 
-    # test suite for module `foo`
-    module test_foo
-    import foo # can be intrude to test private things
-    class TestFoo
-        # test case for `foo::Foo::baz`
-        fun test_baz do
-            var subject = new Foo
-            assert subject.baz(1, 2) == 3
-        end
+~~~~
+# test suite for module `foo`
+module test_foo
+import foo # can be intrude to test private things
+class TestFoo
+    # test case for `foo::Foo::baz`
+    fun test_baz do
+        var subject = new Foo
+        assert subject.baz(1, 2) == 3
     end
+end
+~~~~
 
 Test suite can be executed using the same `nitunit` command:
 
@@ -143,112 +156,184 @@ Test suite can be executed using the same `nitunit` command:
 `nitunit` will execute a test for each method named `test_*` in a class named `Test*`
 so multiple tests can be executed for a single method:
 
-    class TestFoo
-        fun test_baz_1 do
-            var subject = new Foo
-            assert subject.baz(1, 2) == 3
-        end
-        fun test_baz_2 do
-            var subject = new Foo
-            assert subject.baz(1, -2) == -1
-        end
+~~~~
+class TestFoo
+    fun test_baz_1 do
+        var subject = new Foo
+        assert subject.baz(1, 2) == 3
+    end
+    fun test_baz_2 do
+        var subject = new Foo
+        assert subject.baz(1, -2) == -1
     end
+end
+~~~~
+
+## Black Box Testing
+
+Sometimes, it is easier to validate a `TestCase` by comparing its output with a text file containing the expected result.
+
+For each TestCase `test_bar` of a TestSuite `test_mod.nit`, if the corresponding file `test_mod.sav/test_bar.res` exists, then the output of the test is compared with the file.
+
+The `diff(1)` command is used to perform the comparison.
+The test is failed if non-zero is returned by `diff`.
+
+~~~
+module test_mod is test_suite
+class TestFoo
+       fun test_bar do
+               print "Hello!"
+       end
+end
+~~~
+
+Where `test_mod.sav/test_bar.res` contains
+
+~~~raw
+Hello!
+~~~
+
+If no corresponding `.res` file exists, then the output of the TestCase is ignored.
+
+## Configuring TestSuites
 
 `TestSuites` also provide methods to configure the test run:
 
 `before_test` and `after_test`: methods called before/after each test case.
 They can be used to factorize repetitive tasks:
 
-    class TestFoo
-        var subject: Foo
-        # Mandatory empty init
-        init do end
-        # Method executed before each test
-        fun before_test do
-            subject = new Foo
-        end
-        fun test_baz_1 do
-            assert subject.baz(1, 2) == 3
-        end
-        fun test_baz_2 do
-            assert subject.baz(1, -2) == -1
-        end
+~~~~
+class TestFoo
+    var subject: Foo
+    # Mandatory empty init
+    init do end
+    # Method executed before each test
+    fun before_test do
+        subject = new Foo
+    end
+    fun test_baz_1 do
+        assert subject.baz(1, 2) == 3
     end
+    fun test_baz_2 do
+        assert subject.baz(1, -2) == -1
+    end
+end
+~~~~
 
 When using custom test attributes, an empty `init` must be declared to allow automatic test running.
 
 `before_module` and `after_module`: methods called before/after each test suite.
 They have to be declared at top level:
 
-    module test_bdd_connector
-    import bdd_connector
-    # Testing the bdd_connector
-    class TestConnector
-        # test cases using a server
-    end
-    # Method executed before testing the module
-    fun before_module do
-        # start server before all test cases
-    end
-    # Method executed after testing the module
-    fun after_module do
-        # stop server after all test cases
-    end
+~~~~
+module test_bdd_connector
+import bdd_connector
+# Testing the bdd_connector
+class TestConnector
+    # test cases using a server
+end
+# Method executed before testing the module
+fun before_module do
+    # start server before all test cases
+end
+# Method executed after testing the module
+fun after_module do
+    # stop server after all test cases
+end
+~~~~
 
 ## Generating test suites
 
- Write test suites for big modules can be a repetitive and boring task...
- To make it easier, `nitunit` can generate test skeletons for Nit modules:
+Write test suites for big modules can be a repetitive and boring task...
+To make it easier, `nitunit` can generate test skeletons for Nit modules:
 
     $ nitunit --gen-suite foo.nit
 
- This will generate the test suite `test_foo` containing test case stubs for all public
- methods found in `foo.nit`.
+This will generate the test suite `test_foo` containing test case stubs for all public
+methods found in `foo.nit`.
 
 
 # OPTIONS
 
-`--full`
-:   Process also imported modules.
+### `--full`
+Process also imported modules.
+
+By default, only the modules indicated on the command line are tested.
+
+With the `--full` option, all imported modules (even those in standard) are also precessed.
 
-    By default, only the modules indicated on the command line are tested.
+### `-o`, `--output`
+Output name (default is 'nitunit.xml').
 
-    With the `--full` option, all imported modules (even those in standard) are also precessed.
+`nitunit` produces a XML file compatible with JUnit.
 
-`-o`, `--output`
-:   Output name (default is 'nitunit.xml')
+### `--dir`
+Working directory (default is '.nitunit').
 
-    `nitunit` produces a XML file comatible with JUnit.
+In order to execute the tests, nit files are generated then compiled and executed in the giver working directory.
 
-`--dir`
-:   Working directory (default is '.nitunit')
+### `--nitc`
+nitc compiler to use.
 
-    In order to execute the tests, nit files are generated then compiled and executed in the giver working directory.
+By default, nitunit tries to locate the `nitc` program with the environment variable `NITC` or heuristics.
+The option is used to indicate a specific nitc binary.
 
-`--no-act`
-:   Does not compile and run tests.
+### `--no-act`
+Does not compile and run tests.
 
-`-p`, `--pattern`
-:   Only run test case with name that match pattern. Examples: `TestFoo`, `TestFoo*`, `TestFoo::test_foo`, `TestFoo::test_foo*`, `test_foo`, `test_foo*`
+### `-p`, `--pattern`
+Only run test case with name that match pattern.
 
-`-t`, `--target-file`
-:   Specify test suite location.
+Examples: `TestFoo`, `TestFoo*`, `TestFoo::test_foo`, `TestFoo::test_foo*`, `test_foo`, `test_foo*`
+
+### `-t`, `--target-file`
+Specify test suite location.
 
 ## SUITE GENERATION
 
-`--gen-suite`
-:   Generate test suite skeleton for a module
+### `--gen-suite`
+Generate test suite skeleton for a module.
+
+### `-f`, `--force`
+Force test generation even if file exists.
+
+Any existing test suite will be overwritten.
+
+### `--private`
+Also generate test case for private methods.
+
+### `--only-show`
+Only display the skeleton, do not write any file.
+
+
+# ENVIRONMENT VARIABLES
+
+### `NITC`
+
+Indicate the specific Nit compiler executable to use. See `--nitc`.
+
+### `NIT_TESTING`
+
+The environment variable `NIT_TESTING` is set to `true` during the execution of program tests.
+Some libraries of programs can use it to produce specific reproducible results; or just to exit their executions.
+
+Unit-tests may unset this environment variable to retrieve the original behavior of such piece of software.
+
+### `SRAND`
+
+In order to maximize reproducibility, `SRAND` is set to 0.
+This make the pseudo-random generator no random at all.
+See `Sys::srand` for details.
+
+To retrieve the randomness, unit-tests may unset this environment variable then call `srand`.
 
-`-f`, `--force`
-:   Force test generation even if file exists.
+### `NIT_TESTING_ID`
 
-    Any existing test suite will be overwritten.
+Parallel executions can cause some race collisions on named resources (e.g. DB table names).
+To solve this issue, `NIT_TESTING_ID` is initialized with a distinct integer identifier that can be used to give unique names to resources.
 
-`--private`
-:   Also generate test case for private methods.
+Note: `rand` is not a recommended way to get a distinct identifier because its randomness is disabled by default. See `SRAND`.
 
-`--only-show`
-:   Only display the skeleton, do not write any file.
 
 # SEE ALSO