Merge: doc: fixed some typos and other misc. corrections
[nit.git] / src / testing / testing_base.nit
index f814edc..e035c9e 100644 (file)
@@ -31,6 +31,8 @@ redef class ToolContext
        var opt_noact = new OptionBool("Does not compile and run tests", "--no-act")
        # opt --nitc
        var opt_nitc = new OptionString("nitc compiler to use", "--nitc")
+       # opt --no-time
+       var opt_no_time = new OptionBool("Disable time information in XML", "--no-time")
 
        # Working directory for testing.
        fun test_dir: String do
@@ -62,8 +64,8 @@ redef class ToolContext
                        return nitc
                end
 
-               var nit_dir = nit_dir
-               nitc = nit_dir/"bin/nitc"
+               var nit_dir = nit_dir or else "."
+               nitc = nit_dir / "bin/nitc"
                if not nitc.file_exists then
                        fatal_error(null, "Error: cannot find nitc. Set envvar NIT_DIR or NITC or use the --nitc option.")
                        abort
@@ -97,15 +99,18 @@ ulimit -t {{{ulimit_usertime}}} 2> /dev/null
 
        # Show a single-line status to use as a progression.
        #
-       # Note that the line starts with `'\r'` and is not ended by a `'\n'`.
+       # If `has_progress_bar` is true, then the output is a progress bar.
+       # The printed the line starts with `'\r'` and is not ended by a `'\n'`.
        # So it is expected that:
        # * no other output is printed between two calls
        # * the last `show_unit_status` is followed by a new-line
+       #
+       # If `has_progress_bar` is false, then only the first and last state is shown
        fun show_unit_status(name: String, tests: SequenceRead[UnitTest])
        do
-               var esc = 27.code_point.to_s
-               var line = "\r{esc}[K* {name} ["
+               var line = "\r\x1B[K==== {name} ["
                var done = tests.length
+               var fails = 0
                for t in tests do
                        if not t.is_done then
                                line += " "
@@ -114,35 +119,46 @@ ulimit -t {{{ulimit_usertime}}} 2> /dev/null
                                line += ".".green.bold
                        else
                                line += "X".red.bold
+                               fails += 1
                        end
                end
 
-               if not has_status then
+               if not has_progress_bar then
                        if done == 0 then
-                               print "* {name} ({tests.length} tests)"
+                               print "==== {name} | tests: {tests.length}"
                        end
                        return
                end
 
-               line += "] {done}/{tests.length}"
+               if done < tests.length then
+                       line += "] {done}/{tests.length}"
+               else
+                       line += "] tests: {tests.length} "
+                       if fails == 0 then
+                               line += "OK".green.bold
+                       else
+                               line += "KO: {fails}".red.bold
+                       end
+               end
                printn "{line}"
        end
 
-       # Is a status bar printed?
+       # Is a progress bar printed?
        #
-       # true if color and non-verbose mode
-       fun has_status: Bool
+       # true if color (because and non-verbose mode
+       # (because verbose mode messes up with the progress bar).
+       fun has_progress_bar: Bool
        do
                return not opt_no_color.value and opt_verbose.value <= 0
        end
 
-       # Clear the line if `has_status` (no-op else)
-       fun clear_status
+       # Clear the line if `has_progress_bar` (no-op else)
+       fun clear_progress_bar
        do
-               if has_status then printn "\r\x1B[K"
+               if has_progress_bar then printn "\r\x1B[K"
        end
 
-       # Shoe the full description of the test-case.
+       # Show the full description of the test-case.
        #
        # The output honors `--no-color`.
        #
@@ -150,6 +166,13 @@ ulimit -t {{{ulimit_usertime}}} 2> /dev/null
        fun show_unit(test: UnitTest, more_message: nullable String) do
                print test.to_screen(more_message, not opt_no_color.value)
        end
+
+       # Set the `NIT_TESTING_PATH` environment variable with `path`.
+       #
+       # If `path == null` then `NIT_TESTING_PATH` is set with the empty string.
+       fun set_testing_path(path: nullable String) do
+               "NIT_TESTING_PATH".setenv(path or else "")
+       end
 end
 
 # A unit test is an elementary test discovered, run and reported by nitunit.
@@ -183,6 +206,12 @@ abstract class UnitTest
        # The location where the error occurred, if it makes sense.
        var error_location: nullable Location = null is writable
 
+       # Additional noteworthy information when a test success.
+       var info: nullable String = null
+
+       # Time for the execution, in seconds
+       var real_time: Float = 0.0 is writable
+
        # A colorful `[OK]` or `[KO]`.
        fun status_tag(color: nullable Bool): String do
                color = color or else true
@@ -221,6 +250,10 @@ abstract class UnitTest
                else
                        res = "{status_tag(color)} {full_name}"
                        if more_message != null then res += more_message
+                       var info = self.info
+                       if info != null then
+                               res += "\n     {info}"
+                       end
                end
                return res
        end
@@ -230,17 +263,23 @@ abstract class UnitTest
                var tc = new HTMLTag("testcase")
                tc.attr("classname", xml_classname)
                tc.attr("name", xml_name)
+               tc.attr("time", real_time.to_s)
+
+               var output = self.raw_output
+               if output != null then output = output.trunc(8192).filter_nonprintable
                var error = self.error
                if error != null then
+                       var node
                        if was_exec then
-                               tc.open("error").append(error)
+                               node = tc.open("error").attr("message", error)
                        else
-                               tc.open("failure").append(error)
+                               node = tc.open("failure").attr("message", error)
                        end
-               end
-               var output = self.raw_output
-               if output != null then
-                       tc.open("system-err").append(output.trunc(8192).filter_nonprintable)
+                       if output != null then
+                               node.append(output)
+                       end
+               else if output != null then
+                       tc.open("system-err").append(output)
                end
                return tc
        end