Merge: Added contributing guidelines and link from readme
[nit.git] / src / testing / testing_base.nit
index 88651ef..36ce1f9 100644 (file)
@@ -35,7 +35,7 @@ redef class ToolContext
        # Working directory for testing.
        fun test_dir: String do
                var dir = opt_dir.value
-               if dir == null then return ".nitunit"
+               if dir == null then return "nitunit.out"
                return dir
        end
 
@@ -97,15 +97,19 @@ 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
-       fun show_unit_status(name: String, tests: SequenceRead[UnitTest], more_message: nullable String)
+       #
+       # 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,15 +118,53 @@ ulimit -t {{{ulimit_usertime}}} 2> /dev/null
                                line += ".".green.bold
                        else
                                line += "X".red.bold
+                               fails += 1
+                       end
+               end
+
+               if not has_progress_bar then
+                       if done == 0 then
+                               print "==== {name} | tests: {tests.length}"
                        end
+                       return
                end
-               line += "] {done}/{tests.length}"
-               if more_message != null then
-                       line += " " + more_message
+
+               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 progress bar printed?
+       #
+       # 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_progress_bar` (no-op else)
+       fun clear_progress_bar
+       do
+               if has_progress_bar then printn "\r\x1B[K"
+       end
+
+       # Show the full description of the test-case.
+       #
+       # The output honors `--no-color`.
+       #
+       # `more message`, if any, is added after the error message.
+       fun show_unit(test: UnitTest, more_message: nullable String) do
+               print test.to_screen(more_message, not opt_no_color.value)
+       end
 end
 
 # A unit test is an elementary test discovered, run and reported by nitunit.
@@ -156,34 +198,51 @@ 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
+
        # A colorful `[OK]` or `[KO]`.
-       fun status_tag: String do
+       fun status_tag(color: nullable Bool): String do
+               color = color or else true
                if not is_done then
                        return "[  ]"
                else if error != null then
-                       return "[KO]".red.bold
+                       var res = "[KO]"
+                       if color then res = res.red.bold
+                       return res
                else
-                       return "[OK]".green.bold
+                       var res = "[OK]"
+                       if color then res = res.green.bold
+                       return res
                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
+       fun to_screen(more_message: nullable String, color: nullable Bool): String do
+               color = color or else true
                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")}"
+                       if color then
+                               res = "{status_tag(color)} {full_name}\n     {loc.to_s.yellow}: {error}\n{loc.colored_line("1;31")}"
+                       else
+                               res = "{status_tag(color)} {full_name}\n     {loc}: {error}"
+                       end
                        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}"
+                       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