nitunit: separate the error message from the test output
authorJean Privat <jean@pryen.org>
Wed, 25 May 2016 00:10:27 +0000 (20:10 -0400)
committerJean Privat <jean@pryen.org>
Wed, 25 May 2016 14:34:22 +0000 (10:34 -0400)
Signed-off-by: Jean Privat <jean@pryen.org>

src/testing/testing_base.nit
src/testing/testing_doc.nit
src/testing/testing_suite.nit

index 7db143e..62bf57e 100644 (file)
@@ -18,6 +18,7 @@ module testing_base
 import modelize
 private import parser_util
 import html
+import console
 
 redef class ToolContext
        # opt --full
@@ -109,6 +110,8 @@ abstract class UnitTest
        var is_done: Bool = false is writable
 
        # Error message occurred during test-case execution (or compilation).
+       #
+       # e.g.: `Runtime Error`
        var error: nullable String = null is writable
 
        # Was the test case executed at least once?
@@ -124,6 +127,38 @@ abstract class UnitTest
        # The location where the error occurred, if it makes sense.
        var error_location: nullable Location = null is writable
 
+       # A colorful `[OK]` or `[KO]`.
+       fun status_tag: String do
+               if not is_done then
+                       return "[  ]"
+               else if error != null then
+                       return "[KO]".red.bold
+               else
+                       return "[OK]".green.bold
+               end
+       end
+
+       # The full (color) description of the test-case.
+       #
+       # `more message`, if any, is added after the error message.
+       fun to_screen(more_message: nullable String): String do
+               var res
+               var error = self.error
+               if error != null then
+                       if more_message != null then error += " " + more_message
+                       var loc = error_location or else location
+                       res = "{status_tag} {full_name}\n     {loc.to_s.yellow}: {error}\n{loc.colored_line("1;31")}"
+                       var output = self.raw_output
+                       if output != null then
+                               res += "\n     Output\n\t{output.chomp.replace("\n", "\n\t")}\n"
+                       end
+               else
+                       res = "{status_tag} {full_name}"
+                       if more_message != null then res += more_message
+               end
+               return res
+       end
+
        # Return a `<testcase>` XML node in format compatible with Jenkins unit tests.
        fun to_xml: HTMLTag do
                var tc = new HTMLTag("testcase")
@@ -132,11 +167,14 @@ abstract class UnitTest
                var error = self.error
                if error != null then
                        if was_exec then
-                               tc.open("error").append("Runtime Error")
+                               tc.open("error").append(error)
                        else
-                               tc.open("failure").append("Compilation Error")
+                               tc.open("failure").append(error)
                        end
-                       tc.open("system-err").append(error.trunc(8192).filter_nonprintable)
+               end
+               var output = self.raw_output
+               if output != null then
+                       tc.open("system-err").append(output.trunc(8192).filter_nonprintable)
                end
                return tc
        end
index fab4bb7..6a27637 100644 (file)
@@ -70,8 +70,6 @@ class NitUnitExecutor
 
                # Populate `blocks` from the markdown decorator
                mdproc.process(mdoc.content.join("\n"))
-
-               toolcontext.check_errors
        end
 
        # All extracted docunits
@@ -104,6 +102,10 @@ class NitUnitExecutor
                test_simple_docunits(simple_du)
 
                for du in docunits do
+                       print du.to_screen
+               end
+
+               for du in docunits do
                        testsuite.add du.to_xml
                end
        end
@@ -160,15 +162,13 @@ class NitUnitExecutor
                        du.was_exec = true
 
                        var content = "{file}.out1".to_path.read_all
-                       var msg = content.trunc(8192).filter_nonprintable
+                       du.raw_output = content
 
                        if res2 != 0 then
-                               du.error = content
-                               toolcontext.warning(du.location, "error", "ERROR: {du.full_name} (in {file}): Runtime error\n{msg}")
+                               du.error = "Runtime error in {file} with argument {i}"
                                toolcontext.modelbuilder.failed_entities += 1
                        end
                        mark_done(du)
-                       toolcontext.check_errors
                end
        end
 
@@ -196,19 +196,16 @@ class NitUnitExecutor
                end
 
                var content = "{file}.out1".to_path.read_all
-               var msg = content.trunc(8192).filter_nonprintable
+               du.raw_output = content
 
                if res != 0 then
-                       du.error = content
-                       toolcontext.warning(du.location, "failure", "FAILURE: {du.full_name} (in {file}):\n{msg}")
+                       du.error = "Compilation error in {file}"
                        toolcontext.modelbuilder.failed_entities += 1
                else if res2 != 0 then
-                       du.error = content
-                       toolcontext.warning(du.location, "error", "ERROR: {du.full_name} (in {file}):\n{msg}")
+                       du.error = "Runtime error in {file}"
                        toolcontext.modelbuilder.failed_entities += 1
                end
                mark_done(du)
-               toolcontext.check_errors
        end
 
        # Create and fill the header of a unit file `file`.
@@ -300,9 +297,6 @@ private class NitunitDecorator
                                message = "Error: Invalid Nit code."
                        end
 
-                       executor.toolcontext.warning(location, "invalid-block", "{message} To suppress this message, enclose the block with a fence tagged `nitish` or `raw` (see `man nitdoc`).")
-                       executor.toolcontext.modelbuilder.failed_entities += 1
-
                        var du = new_docunit
                        du.block += code
                        du.error_location = location
index 59b4499..6a10288 100644 (file)
@@ -145,6 +145,9 @@ class TestSuite
                for case in test_cases do case.run
                var after_module = self.after_module
                if not after_module == null then after_module.run
+               for case in test_cases do
+                       print case.to_screen
+               end
        end
 
        # Write the test unit for `self` in a nit compilable file.
@@ -254,17 +257,13 @@ class TestCase
                var test_file = test_suite.test_file
                var res_name = "{test_file}_{method_name.escape_to_c}"
                var res = toolcontext.safe_exec("{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
+               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
@@ -273,10 +272,8 @@ class TestCase
                                        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
-                                               msg = "Diff\n" + "{res_name}.diff".to_path.read_all
-                                               error = msg
-                                               toolcontext.warning(loc, "failure",
-                                               "ERROR: {method_name} (in file {test_file}.nit): {msg}")
+                                               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
@@ -285,7 +282,6 @@ class TestCase
                        end
                end
                is_done = true
-               toolcontext.check_errors
        end
 
        redef fun xml_classname do