nitunit: honor --no-color
[nit.git] / src / testing / testing_suite.nit
index 0de6e0a..f755d25 100644 (file)
@@ -132,8 +132,14 @@ class TestSuite
        # Test to be executed after the whole test suite.
        var after_module: nullable TestCase = null
 
+       fun show_status(more_message: nullable String)
+       do
+               toolcontext.show_unit_status("Test-suite of module " + mmodule.full_name, test_cases, more_message)
+       end
+
        # Execute the test suite
        fun run do
+               show_status
                if not toolcontext.test_dir.file_exists then
                        toolcontext.test_dir.mkdir
                end
@@ -142,9 +148,19 @@ class TestSuite
                toolcontext.info("Execute test-suite {mmodule.name}", 1)
                var before_module = self.before_module
                if not before_module == null then before_module.run
-               for case in test_cases do case.run
+               for case in test_cases do
+                       case.run
+                       show_status(case.full_name + " " + case.status_tag)
+               end
+
+               show_status
+               print ""
+
                var after_module = self.after_module
                if not after_module == null then after_module.run
+               for case in test_cases do
+                       toolcontext.show_unit(case)
+               end
        end
 
        # Write the test unit for `self` in a nit compilable file.
@@ -183,12 +199,7 @@ class TestSuite
        # Compile all `test_cases` cases in one file.
        fun compile do
                # find nitc
-               var nit_dir = toolcontext.nit_dir
-               var nitc = nit_dir/"bin/nitc"
-               if not nitc.file_exists then
-                       toolcontext.error(null, "Error: cannot find nitc. Set envvar NIT_DIR.")
-                       toolcontext.check_errors
-               end
+               var nitc = toolcontext.find_nitc
                # compile test suite
                var file = test_file
                var module_file = mmodule.location.file
@@ -199,7 +210,7 @@ class TestSuite
                end
                var include_dir = module_file.filename.dirname
                var cmd = "{nitc} --no-color '{file}.nit' -I {include_dir} -o '{file}.bin' > '{file}.out' 2>&1 </dev/null"
-               var res = sys.system(cmd)
+               var res = toolcontext.safe_exec(cmd)
                var f = new FileReader.open("{file}.out")
                var msg = f.read_all
                f.close
@@ -219,6 +230,7 @@ end
 
 # A test case is a unit test considering only a `MMethodDef`.
 class TestCase
+       super UnitTest
 
        # Test suite wich `self` belongs to.
        var test_suite: TestSuite
@@ -226,6 +238,10 @@ class TestCase
        # Test method to be compiled and tested.
        var test_method: MMethodDef
 
+       redef fun full_name do return test_method.full_name
+
+       redef fun location do return test_method.location
+
        # `ToolContext` to use to display messages and find `nitc` bin.
        var toolcontext: ToolContext
 
@@ -253,47 +269,41 @@ class TestCase
                var method_name = test_method.name
                var test_file = test_suite.test_file
                var res_name = "{test_file}_{method_name.escape_to_c}"
-               var res = sys.system("{test_file}.bin {method_name} > '{res_name}.out1' 2>&1 </dev/null")
-               var f = new FileReader.open("{res_name}.out1")
-               var msg = f.read_all
-               f.close
+               var res = toolcontext.safe_exec("{test_file}.bin {method_name} > '{res_name}.out1' 2>&1 </dev/null")
+               self.raw_output = "{res_name}.out1".to_path.read_all
                # set test case result
-               var loc = test_method.location
                if res != 0 then
-                       error = msg
-                       toolcontext.warning(loc, "failure",
-                          "ERROR: {method_name} (in file {test_file}.nit): {msg}")
+                       error = "Runtime Error in file {test_file}.nit"
                        toolcontext.modelbuilder.failed_tests += 1
+               else
+                       # no error, check with res file, if any.
+                       var mmodule = test_method.mclassdef.mmodule
+                       var file = mmodule.filepath
+                       if file != null then
+                               var sav = file.dirname / mmodule.name + ".sav" / test_method.name + ".res"
+                               if sav.file_exists then
+                                       toolcontext.info("Diff output with {sav}", 1)
+                                       res = toolcontext.safe_exec("diff -u --label 'expected:{sav}' --label 'got:{res_name}.out1' '{sav}' '{res_name}.out1' > '{res_name}.diff' 2>&1 </dev/null")
+                                       if res != 0 then
+                                               self.raw_output = "Diff\n" + "{res_name}.diff".to_path.read_all
+                                               error = "Difference with expected output: diff -u {sav} {res_name}.out1"
+                                               toolcontext.modelbuilder.failed_tests += 1
+                                       end
+                               else
+                                       toolcontext.info("No diff: {sav} not found", 2)
+                               end
+                       end
                end
-               toolcontext.check_errors
+               is_done = true
        end
 
-       # Error occured during test-case execution.
-       var error: nullable String = null
-
-       # Was the test case executed at least one?
-       var was_exec = false
-
-       # Return the `TestCase` in XML format compatible with Jenkins.
-       fun to_xml: HTMLTag do
+       redef fun xml_classname do
                var mclassdef = test_method.mclassdef
-               var tc = new HTMLTag("testcase")
-               # NOTE: jenkins expects a '.' in the classname attr
-               tc.attr("classname", "nitunit." + mclassdef.mmodule.full_name + "." + mclassdef.mclass.full_name)
-               tc.attr("name", test_method.mproperty.full_name)
-               if was_exec then
-                       tc.add  new HTMLTag("system-err")
-                       var n = new HTMLTag("system-out")
-                       n.append "out"
-                       tc.add n
-                       var error = self.error
-                       if error != null then
-                               n = new HTMLTag("error")
-                               n.attr("message", error.to_s)
-                               tc.add n
-                       end
-               end
-               return tc
+               return "nitunit." + mclassdef.mmodule.full_name + "." + mclassdef.mclass.full_name
+       end
+
+       redef fun xml_name do
+               return test_method.mproperty.full_name
        end
 end