Merge: Refactorize nitunit
authorJean Privat <jean@pryen.org>
Sun, 22 May 2016 12:56:17 +0000 (08:56 -0400)
committerJean Privat <jean@pryen.org>
Sun, 22 May 2016 12:56:17 +0000 (08:56 -0400)
Future improvement of nitunit require a saner codebase.
This PR does not bring a lot of features but propose instead some code improvements.

Summary:

* a new class UnitTest to factorize DocUnit and TestCase
* DocUnit are created, with its metadata, while discovered
* DocUnit do not enclose a XML node to fill but will generate one with to_xml.
* Easter egg: precise locations are included in the DocUnits. Each line of *collected* code can be located back to the original source code. This feature is not really used yet, except to locate the docunit itself.

The last commits are divided in order to make the reviewing more easy. I tought that is was better than a big stashed change.

Future PR will target usability since unit-tests are now reified in a common way on both sides (docunits and testsuites).

Pull-Request: #2114
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>

src/testing/testing_base.nit
src/testing/testing_doc.nit
src/testing/testing_suite.nit
tests/sav/nitunit_args1.res
tests/sav/nitunit_args4.res
tests/sav/nitunit_args5.res
tests/sav/nitunit_args6.res
tests/sav/nitunit_args7.res
tests/sav/nitunit_args8.res
tests/sav/nitunit_args9.res

index 414de9a..4249df5 100644 (file)
@@ -17,6 +17,7 @@ module testing_base
 
 import modelize
 private import parser_util
+import html
 
 redef class ToolContext
        # opt --full
@@ -94,6 +95,47 @@ ulimit -t {{{ulimit_usertime}}} 2> /dev/null
        var ulimit_usertime = 600 is writable
 end
 
+# A unit test is an elementary test discovered, run and reported bu nitunit.
+#
+# This class factorizes `DocUnit` and `TestCase`.
+abstract class UnitTest
+
+       # Error occurred during test-case execution.
+       var error: nullable String = null is writable
+
+       # Was the test case executed at least once?
+       var was_exec = false is writable
+
+       # Return the `TestCase` in XML format compatible with Jenkins.
+       #
+       # See to_xml
+       fun to_xml: HTMLTag do
+               var tc = new HTMLTag("testcase")
+               tc.attr("classname", xml_classname)
+               tc.attr("name", xml_name)
+               var error = self.error
+               if error != null then
+                       if was_exec then
+                               tc.open("error").append("Runtime Error")
+                       else
+                               tc.open("failure").append("Compilation Error")
+                       end
+                       tc.open("system-err").append(error.trunc(8192).filter_nonprintable)
+               end
+               return tc
+       end
+
+       # The `classname` attribute of the XML format.
+       #
+       # NOTE: jenkins expects a '.' in the classname attr
+       fun xml_classname: String is abstract
+
+       # The `name` attribute of the XML format.
+       #
+       # See to_xml
+       fun xml_name: String is abstract
+end
+
 redef class String
        # If needed, truncate `self` at `max_length` characters and append an informative `message`.
        #
index 05c1f67..1ea2cf7 100644 (file)
@@ -36,12 +36,6 @@ class NitUnitExecutor
        # The XML node associated to the module
        var testsuite: HTMLTag
 
-       # All blocks of code from a same `ADoc`
-       var blocks = new Array[Buffer]
-
-       # All failures from a same `ADoc`
-       var failures = new Array[String]
-
        # Markdown processor used to parse markdown comments and extract code.
        var mdproc = new MarkdownProcessor
 
@@ -55,14 +49,22 @@ class NitUnitExecutor
        # used to generate distinct names
        var cpt = 0
 
+       # The last docunit extracted from a mdoc.
+       #
+       # Is used because a new code-block might just be added to it.
+       var last_docunit: nullable DocUnit = null
+
+       var xml_classname: String is noautoinit
+
+       var xml_name: String is noautoinit
+
        # The entry point for a new `ndoc` node
        # Fill `docunits` with new discovered unit of tests.
-       #
-       # `tc` (testcase) is the pre-filled XML node
-       fun extract(mdoc: MDoc, tc: HTMLTag)
+       fun extract(mdoc: MDoc, xml_classname, xml_name: String)
        do
-               blocks.clear
-               failures.clear
+               last_docunit = null
+               self.xml_classname = xml_classname
+               self.xml_name = xml_name
 
                self.mdoc = mdoc
 
@@ -70,22 +72,6 @@ class NitUnitExecutor
                mdproc.process(mdoc.content.join("\n"))
 
                toolcontext.check_errors
-
-               if not failures.is_empty then
-                       for msg in failures do
-                               var ne = new HTMLTag("failure")
-                               ne.attr("message", msg)
-                               tc.add ne
-                               toolcontext.modelbuilder.unit_entities += 1
-                               toolcontext.modelbuilder.failed_entities += 1
-                       end
-                       if blocks.is_empty then testsuite.add(tc)
-               end
-
-               if blocks.is_empty then return
-               for block in blocks do
-                       docunits.add new DocUnit(mdoc, tc, block.write_to_string)
-               end
        end
 
        # All extracted docunits
@@ -96,6 +82,9 @@ class NitUnitExecutor
        do
                var simple_du = new Array[DocUnit]
                for du in docunits do
+                       # Skip existing errors
+                       if du.error != null then continue
+
                        var ast = toolcontext.parse_something(du.block)
                        if ast isa AExpr then
                                simple_du.add du
@@ -105,6 +94,10 @@ class NitUnitExecutor
                end
 
                test_simple_docunits(simple_du)
+
+               for du in docunits do
+                       testsuite.add du.to_xml
+               end
        end
 
        # Executes multiples doc-units in a shared program.
@@ -128,7 +121,7 @@ class NitUnitExecutor
 
                        i += 1
                        f.write("fun run_{i} do\n")
-                       f.write("# {du.testcase.attrs["name"]}\n")
+                       f.write("# {du.full_name}\n")
                        f.write(du.block)
                        f.write("end\n")
                end
@@ -153,35 +146,19 @@ class NitUnitExecutor
 
                i = 0
                for du in dus do
-                       var tc = du.testcase
-                       toolcontext.modelbuilder.unit_entities += 1
                        i += 1
-                       toolcontext.info("Execute doc-unit {du.testcase.attrs["name"]} in {file} {i}", 1)
+                       toolcontext.info("Execute doc-unit {du.full_name} in {file} {i}", 1)
                        var res2 = toolcontext.safe_exec("{file.to_program_name}.bin {i} >'{file}.out1' 2>&1 </dev/null")
 
-                       f = new FileReader.open("{file}.out1")
-                       var n2
-                       n2 = new HTMLTag("system-err")
-                       tc.add n2
-                       var content = f.read_all
+                       var content = "{file}.out1".to_path.read_all
                        var msg = content.trunc(8192).filter_nonprintable
-                       n2.append(msg)
-                       f.close
-
-                       n2 = new HTMLTag("system-out")
-                       tc.add n2
-                       n2.append(du.block)
 
                        if res2 != 0 then
-                               var ne = new HTMLTag("error")
-                               ne.attr("message", "Runtime error")
-                               tc.add ne
-                               toolcontext.warning(du.mdoc.location, "error", "ERROR: {tc.attrs["classname"]}.{tc.attrs["name"]} (in {file}): Runtime error\n{msg}")
+                               du.error = content
+                               toolcontext.warning(du.location, "error", "ERROR: {du.full_name} (in {file}): Runtime error\n{msg}")
                                toolcontext.modelbuilder.failed_entities += 1
                        end
                        toolcontext.check_errors
-
-                       testsuite.add(tc)
                end
        end
 
@@ -189,13 +166,10 @@ class NitUnitExecutor
        # Used for docunits larger than a single block of code (with modules, classes, functions etc.)
        fun test_single_docunit(du: DocUnit)
        do
-               var tc = du.testcase
-               toolcontext.modelbuilder.unit_entities += 1
-
                cpt += 1
                var file = "{prefix}-{cpt}.nit"
 
-               toolcontext.info("Execute doc-unit {tc.attrs["name"]} in {file}", 1)
+               toolcontext.info("Execute doc-unit {du.full_name} in {file}", 1)
 
                var f
                f = create_unitfile(file)
@@ -210,36 +184,18 @@ class NitUnitExecutor
                        res2 = toolcontext.safe_exec("{file.to_program_name}.bin >'{file}.out1' 2>&1 </dev/null")
                end
 
-               f = new FileReader.open("{file}.out1")
-               var n2
-               n2 = new HTMLTag("system-err")
-               tc.add n2
-               var content = f.read_all
+               var content = "{file}.out1".to_path.read_all
                var msg = content.trunc(8192).filter_nonprintable
-               n2.append(msg)
-               f.close
-
-               n2 = new HTMLTag("system-out")
-               tc.add n2
-               n2.append(du.block)
-
 
                if res != 0 then
-                       var ne = new HTMLTag("failure")
-                       ne.attr("message", "Compilation Error")
-                       tc.add ne
-                       toolcontext.warning(du.mdoc.location, "failure", "FAILURE: {tc.attrs["classname"]}.{tc.attrs["name"]} (in {file}):\n{msg}")
+                       du.error = content
+                       toolcontext.warning(du.location, "failure", "FAILURE: {du.full_name} (in {file}):\n{msg}")
                        toolcontext.modelbuilder.failed_entities += 1
                else if res2 != 0 then
-                       var ne = new HTMLTag("error")
-                       ne.attr("message", "Runtime Error")
-                       tc.add ne
-                       toolcontext.warning(du.mdoc.location, "error", "ERROR: {tc.attrs["classname"]}.{tc.attrs["name"]} (in {file}):\n{msg}")
+                       toolcontext.warning(du.location, "error", "ERROR: {du.full_name} (in {file}):\n{msg}")
                        toolcontext.modelbuilder.failed_entities += 1
                end
                toolcontext.check_errors
-
-               testsuite.add(tc)
        end
 
        # Create and fill the header of a unit file `file`.
@@ -332,31 +288,122 @@ private class NitunitDecorator
                        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.failures.add("{location}: {message}")
+                       executor.toolcontext.modelbuilder.failed_entities += 1
+
+                       var du = new_docunit
+                       du.block += code
+                       du.error = "{location}: {message}"
                        return
                end
 
                # Create a first block
                # Or create a new block for modules that are more than a main part
-               if executor.blocks.is_empty or ast isa AModule then
-                       executor.blocks.add(new Buffer)
+               var last_docunit = executor.last_docunit
+               if last_docunit == null or ast isa AModule then
+                       last_docunit = new_docunit
+                       executor.last_docunit = last_docunit
                end
 
                # Add it to the file
-               executor.blocks.last.append code
+               last_docunit.block += code
+
+               # In order to retrieve precise positions,
+               # the real position of each line of the raw_content is stored.
+               # See `DocUnit::real_location`
+               line_offset -= loc.line_start - 1
+               for i in [loc.line_start..loc.line_end] do
+                       last_docunit.lines.add i + line_offset
+                       last_docunit.columns.add column_offset
+               end
+       end
+
+       # Return and register a new empty docunit
+       fun new_docunit: DocUnit
+       do
+               var mdoc = executor.mdoc
+               assert mdoc != null
+
+               var next_number = 0
+               var name = executor.xml_name
+               if executor.docunits.not_empty and executor.docunits.last.mdoc == mdoc then
+                       next_number = executor.docunits.last.number + 1
+                       name += "+" + next_number.to_s
+               end
+
+               var res = new DocUnit(mdoc, next_number, "", executor.xml_classname, name)
+               executor.docunits.add res
+               executor.toolcontext.modelbuilder.unit_entities += 1
+               return res
        end
 end
 
-# A unit-test to run
+# A unit-test extracted from some documentation.
+#
+# A docunit is extracted from the code-blocks of mdocs.
+# Each mdoc can contains more than one docunit, and a single docunit can be made of more that a single code-block.
 class DocUnit
+       super UnitTest
+
        # The doc that contains self
        var mdoc: MDoc
 
-       # The XML node that contains the information about the execution
-       var testcase: HTMLTag
+       # The numbering of self in mdoc (starting with 0)
+       var number: Int
+
+       # The name of the unit to show in messages
+       fun full_name: String do
+               var mentity = mdoc.original_mentity
+               if mentity != null then return mentity.full_name
+               return xml_classname + "." + xml_name
+       end
 
-       # The text of the code to execute
+       # The text of the code to execute.
+       #
+       # This is the verbatim content on one, or more, code-blocks from `mdoc`
        var block: String
+
+       # For each line in `block`, the associated line in the mdoc
+       #
+       # Is used to give precise locations
+       var lines = new Array[Int]
+
+       # For each line in `block`, the associated column in the mdoc
+       #
+       # Is used to give precise locations
+       var columns = new Array[Int]
+
+       # The location of the whole docunit.
+       #
+       # If `self` is made of multiple code-blocks, then the location
+       # starts at the first code-books and finish at the last one, thus includes anything between.
+       var location: Location is lazy do
+               return new Location(mdoc.location.file, lines.first, lines.last+1, columns.first+1, 0)
+       end
+
+       # Compute the real location of a node on the `ast` based on `mdoc.location`
+       #
+       # The result is basically: ast_location + markdown location of the piece + mdoc.location
+       #
+       # The fun is that a single docunit can be made of various pieces of code blocks.
+       fun real_location(ast_location: Location): Location
+       do
+               var mdoc = self.mdoc
+               var res = new Location(mdoc.location.file, lines[ast_location.line_start-1],
+                       lines[ast_location.line_end-1],
+                       columns[ast_location.line_start-1] + ast_location.column_start,
+                       columns[ast_location.line_end-1] + ast_location.column_end)
+               return res
+       end
+
+       redef fun to_xml
+       do
+               var res = super
+               res.open("system-out").append(block)
+               return res
+       end
+
+       redef var xml_classname
+       redef var xml_name
 end
 
 redef class ModelBuilder
@@ -397,8 +444,6 @@ redef class ModelBuilder
                prefix = prefix.join_path(mmodule.to_s)
                var d2m = new NitUnitExecutor(toolcontext, prefix, o, ts)
 
-               var tc
-
                do
                        total_entities += 1
                        var nmoduledecl = nmodule.n_moduledecl
@@ -406,11 +451,8 @@ redef class ModelBuilder
                        var ndoc = nmoduledecl.n_doc
                        if ndoc == null then break label x
                        doc_entities += 1
-                       tc = new HTMLTag("testcase")
                        # NOTE: jenkins expects a '.' in the classname attr
-                       tc.attr("classname", "nitunit." + mmodule.full_name + ".<module>")
-                       tc.attr("name", "<module>")
-                       d2m.extract(ndoc.to_mdoc, tc)
+                       d2m.extract(ndoc.to_mdoc, "nitunit." + mmodule.full_name + ".<module>", "<module>")
                end label x
                for nclassdef in nmodule.n_classdefs do
                        var mclassdef = nclassdef.mclassdef
@@ -420,10 +462,7 @@ redef class ModelBuilder
                                var ndoc = nclassdef.n_doc
                                if ndoc != null then
                                        doc_entities += 1
-                                       tc = new HTMLTag("testcase")
-                                       tc.attr("classname", "nitunit." + mmodule.full_name + "." + mclassdef.mclass.full_name)
-                                       tc.attr("name", "<class>")
-                                       d2m.extract(ndoc.to_mdoc, tc)
+                                       d2m.extract(ndoc.to_mdoc, "nitunit." + mmodule.full_name + "." + mclassdef.mclass.full_name, "<class>")
                                end
                        end
                        for npropdef in nclassdef.n_propdefs do
@@ -433,10 +472,7 @@ redef class ModelBuilder
                                var ndoc = npropdef.n_doc
                                if ndoc != null then
                                        doc_entities += 1
-                                       tc = new HTMLTag("testcase")
-                                       tc.attr("classname", "nitunit." + mmodule.full_name + "." + mclassdef.mclass.full_name)
-                                       tc.attr("name", mpropdef.mproperty.full_name)
-                                       d2m.extract(ndoc.to_mdoc, tc)
+                                       d2m.extract(ndoc.to_mdoc, "nitunit." + mmodule.full_name + "." + mclassdef.mclass.full_name, mpropdef.mproperty.full_name)
                                end
                        end
                end
@@ -462,18 +498,13 @@ redef class ModelBuilder
                prefix = prefix.join_path(mgroup.to_s)
                var d2m = new NitUnitExecutor(toolcontext, prefix, o, ts)
 
-               var tc
-
                total_entities += 1
                var mdoc = mgroup.mdoc
                if mdoc == null then return ts
 
                doc_entities += 1
-               tc = new HTMLTag("testcase")
                # NOTE: jenkins expects a '.' in the classname attr
-               tc.attr("classname", "nitunit." + mgroup.full_name)
-               tc.attr("name", "<group>")
-               d2m.extract(mdoc, tc)
+               d2m.extract(mdoc, "nitunit." + mgroup.full_name, "<group>")
 
                d2m.run_tests
 
@@ -493,17 +524,11 @@ redef class ModelBuilder
                var prefix = toolcontext.test_dir / "file"
                var d2m = new NitUnitExecutor(toolcontext, prefix, null, ts)
 
-               var tc
-
                total_entities += 1
                doc_entities += 1
 
-               tc = new HTMLTag("testcase")
                # NOTE: jenkins expects a '.' in the classname attr
-               tc.attr("classname", "nitunit.<file>")
-               tc.attr("name", file)
-
-               d2m.extract(mdoc, tc)
+               d2m.extract(mdoc, "nitunit.<file>", file)
                d2m.run_tests
 
                return ts
index ae1f4a2..ee2701f 100644 (file)
@@ -214,6 +214,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
@@ -282,32 +283,13 @@ class TestCase
                toolcontext.check_errors
        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-out")
-                       var n = new HTMLTag("system-err")
-                       tc.add n
-                       var error = self.error
-                       if error != null then
-                               n.append error.trunc(8192).filter_nonprintable
-                               n = new HTMLTag("error")
-                               n.attr("message", "Runtime Error")
-                               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
 
index 15eee20..48642c1 100644 (file)
@@ -1,7 +1,7 @@
-test_nitunit.nit:20,1--22,0: ERROR: nitunit.test_nitunit::test_nitunit.test_nitunit::X.<class> (in .nitunit/test_nitunit-2.nit):
+test_nitunit.nit:21,7--22,0: ERROR: test_nitunit$X (in .nitunit/test_nitunit-2.nit):
 Runtime error: Assert failed (.nitunit/test_nitunit-2.nit:5)
 
-test_nitunit.nit:23,2--25,0: FAILURE: nitunit.test_nitunit::test_nitunit.test_nitunit::X.test_nitunit::X::foo (in .nitunit/test_nitunit-3.nit):
+test_nitunit.nit:24,8--25,0: FAILURE: test_nitunit$X$foo (in .nitunit/test_nitunit-3.nit):
 .nitunit/test_nitunit-3.nit:5,8--27: Error: method or variable `undefined_identifier` unknown in `Sys`.
 
 test_test_nitunit.nit:36,2--40,4: ERROR: test_foo1 (in file .nitunit/gen_test_test_nitunit.nit): Runtime error: Assert failed (test_test_nitunit.nit:39)
@@ -11,10 +11,9 @@ Entities: 27; Documented ones: 3; With nitunits: 3; Failures: 2
 
 TestSuites:
 Class suites: 1; Test Cases: 3; Failures: 1
-<testsuites><testsuite package="test_nitunit::test_nitunit"><testcase classname="nitunit.test_nitunit::test_nitunit.&lt;module&gt;" name="&lt;module&gt;"><system-err></system-err><system-out>assert true
-</system-out></testcase><testcase classname="nitunit.test_nitunit::test_nitunit.test_nitunit::X" name="&lt;class&gt;"><system-err>Runtime error: Assert failed (.nitunit&#47;test_nitunit-2.nit:5)
-</system-err><system-out>assert false
-</system-out><error message="Runtime Error"></error></testcase><testcase classname="nitunit.test_nitunit::test_nitunit.test_nitunit::X" name="test_nitunit::X::foo"><system-err>.nitunit&#47;test_nitunit-3.nit:5,8--27: Error: method or variable `undefined_identifier` unknown in `Sys`.
+<testsuites><testsuite package="test_nitunit::test_nitunit"><testcase classname="nitunit.test_nitunit::test_nitunit.&lt;module&gt;" name="&lt;module&gt;"><system-out>assert true
+</system-out></testcase><testcase classname="nitunit.test_nitunit::test_nitunit.test_nitunit::X" name="&lt;class&gt;"><system-out>assert false
+</system-out></testcase><testcase classname="nitunit.test_nitunit::test_nitunit.test_nitunit::X" name="test_nitunit::X::foo"><failure>Compilation Error</failure><system-err>.nitunit&#47;test_nitunit-3.nit:5,8--27: Error: method or variable `undefined_identifier` unknown in `Sys`.
 </system-err><system-out>assert undefined_identifier
-</system-out><failure message="Compilation Error"></failure></testcase></testsuite><testsuite package="test_test_nitunit"><testcase classname="nitunit.test_test_nitunit::test_test_nitunit.test_test_nitunit::TestX" name="test_test_nitunit::TestX::test_foo"><system-out></system-out><system-err></system-err></testcase><testcase classname="nitunit.test_test_nitunit::test_test_nitunit.test_test_nitunit::TestX" name="test_test_nitunit::TestX::test_foo1"><system-out></system-out><system-err>Runtime error: Assert failed (test_test_nitunit.nit:39)
-</system-err><error message="Runtime Error"></error></testcase><testcase classname="nitunit.test_test_nitunit::test_test_nitunit.test_test_nitunit::TestX" name="test_test_nitunit::TestX::test_foo2"><system-out></system-out><system-err></system-err></testcase></testsuite></testsuites>
\ No newline at end of file
+</system-out></testcase></testsuite><testsuite package="test_test_nitunit"><testcase classname="nitunit.test_test_nitunit::test_test_nitunit.test_test_nitunit::TestX" name="test_test_nitunit::TestX::test_foo"></testcase><testcase classname="nitunit.test_test_nitunit::test_test_nitunit.test_test_nitunit::TestX" name="test_test_nitunit::TestX::test_foo1"><error>Runtime Error</error><system-err>Runtime error: Assert failed (test_test_nitunit.nit:39)
+</system-err></testcase><testcase classname="nitunit.test_test_nitunit::test_test_nitunit.test_test_nitunit::TestX" name="test_test_nitunit::TestX::test_foo2"></testcase></testsuite></testsuites>
\ No newline at end of file
index 4f4ab53..4cb3aaa 100644 (file)
@@ -5,17 +5,17 @@ Entities: 4; Documented ones: 3; With nitunits: 3; Failures: 0
 TestSuites:
 No test cases found
 Class suites: 0; Test Cases: 0; Failures: 0
-<testsuites><testsuite package="test_nitunit2::test_nitunit2"><testcase classname="nitunit.test_nitunit2::test_nitunit2.core::Sys" name="test_nitunit2::test_nitunit2::Sys::foo1"><system-err></system-err><system-out>if true then
+<testsuites><testsuite package="test_nitunit2::test_nitunit2"><testcase classname="nitunit.test_nitunit2::test_nitunit2.core::Sys" name="test_nitunit2::test_nitunit2::Sys::foo1"><system-out>if true then
 
    assert true
 
 end
-</system-out></testcase><testcase classname="nitunit.test_nitunit2::test_nitunit2.core::Sys" name="test_nitunit2::test_nitunit2::Sys::bar2"><system-err></system-err><system-out>if true then
+</system-out></testcase><testcase classname="nitunit.test_nitunit2::test_nitunit2.core::Sys" name="test_nitunit2::test_nitunit2::Sys::bar2"><system-out>if true then
 
     assert true
 
 end
-</system-out></testcase><testcase classname="nitunit.test_nitunit2::test_nitunit2.core::Sys" name="test_nitunit2::test_nitunit2::Sys::foo3"><system-err></system-err><system-out>var a = 1
+</system-out></testcase><testcase classname="nitunit.test_nitunit2::test_nitunit2.core::Sys" name="test_nitunit2::test_nitunit2::Sys::foo3"><system-out>var a = 1
 assert a == 1
 assert a == 1
 </system-out></testcase></testsuite><testsuite></testsuite></testsuites>
\ No newline at end of file
index dd4f11a..8fa1c3c 100644 (file)
@@ -5,7 +5,7 @@ Entities: 6; Documented ones: 5; With nitunits: 3; Failures: 0
 TestSuites:
 No test cases found
 Class suites: 0; Test Cases: 0; Failures: 0
-<testsuites><testsuite package="test_doc2::test_doc2"><testcase classname="nitunit.test_doc2::test_doc2.core::Sys" name="test_doc2::test_doc2::Sys::foo1"><system-err></system-err><system-out>assert true # tested
-</system-out></testcase><testcase classname="nitunit.test_doc2::test_doc2.core::Sys" name="test_doc2::test_doc2::Sys::foo2"><system-err></system-err><system-out>assert true # tested
-</system-out></testcase><testcase classname="nitunit.test_doc2::test_doc2.core::Sys" name="test_doc2::test_doc2::Sys::foo3"><system-err></system-err><system-out>assert true # tested
+<testsuites><testsuite package="test_doc2::test_doc2"><testcase classname="nitunit.test_doc2::test_doc2.core::Sys" name="test_doc2::test_doc2::Sys::foo1"><system-out>assert true # tested
+</system-out></testcase><testcase classname="nitunit.test_doc2::test_doc2.core::Sys" name="test_doc2::test_doc2::Sys::foo2"><system-out>assert true # tested
+</system-out></testcase><testcase classname="nitunit.test_doc2::test_doc2.core::Sys" name="test_doc2::test_doc2::Sys::foo3"><system-out>assert true # tested
 </system-out></testcase></testsuite><testsuite></testsuite></testsuites>
\ No newline at end of file
index 2a1e91e..ca7ee6a 100644 (file)
@@ -1,5 +1,5 @@
 test_nitunit3/README.md:7,3--5: Syntax Error: unexpected malformed character '\]. To suppress this message, enclose the block with a fence tagged `nitish` or `raw` (see `man nitdoc`).
-test_nitunit3/README.md:1,0--13,0: ERROR: nitunit.test_nitunit3>.<group> (in .nitunit/test_nitunit3-0.nit): Runtime error
+test_nitunit3/README.md:4,2--15,0: ERROR: test_nitunit3> (in .nitunit/test_nitunit3-0.nit): Runtime error
 Runtime error: Assert failed (.nitunit/test_nitunit3-0.nit:7)
 
 DocUnits:
@@ -8,8 +8,9 @@ Entities: 2; Documented ones: 2; With nitunits: 3; Failures: 2
 TestSuites:
 No test cases found
 Class suites: 0; Test Cases: 0; Failures: 0
-<testsuites><testsuite package="test_nitunit3&gt;"><testcase classname="nitunit.test_nitunit3&gt;" name="&lt;group&gt;"><failure message="test_nitunit3&#47;README.md:7,3--5: Syntax Error: unexpected malformed character &#39;\]."></failure><system-err>Runtime error: Assert failed (.nitunit&#47;test_nitunit3-0.nit:7)
+<testsuites><testsuite package="test_nitunit3&gt;"><testcase classname="nitunit.test_nitunit3&gt;" name="&lt;group&gt;"><failure>Compilation Error</failure><system-err>Runtime error: Assert failed (.nitunit&#47;test_nitunit3-0.nit:7)
 </system-err><system-out>assert false
 assert true
-</system-out><error message="Runtime error"></error></testcase></testsuite><testsuite package="test_nitunit3::test_nitunit3"><testcase classname="nitunit.test_nitunit3::test_nitunit3.&lt;module&gt;" name="&lt;module&gt;"><system-err></system-err><system-out>assert true
+</system-out></testcase><testcase classname="nitunit.test_nitunit3&gt;" name="&lt;group&gt;+1"><failure>Compilation Error</failure><system-err>test_nitunit3&#47;README.md:7,3--5: Syntax Error: unexpected malformed character &#39;\].</system-err><system-out>;&#39;\][]
+</system-out></testcase></testsuite><testsuite package="test_nitunit3::test_nitunit3"><testcase classname="nitunit.test_nitunit3::test_nitunit3.&lt;module&gt;" name="&lt;module&gt;"><system-out>assert true
 </system-out></testcase></testsuite><testsuite></testsuite></testsuites>
\ No newline at end of file
index 436061a..0888b04 100644 (file)
@@ -1,4 +1,4 @@
-test_nitunit_md.md:1,0--15,0: ERROR: nitunit.<file>.test_nitunit_md.md:1,0--15,0 (in .nitunit/file-0.nit): Runtime error
+test_nitunit_md.md:4,2--16,0: ERROR: nitunit.<file>.test_nitunit_md.md:1,0--15,0 (in .nitunit/file-0.nit): Runtime error
 Runtime error: Assert failed (.nitunit/file-0.nit:8)
 
 DocUnits:
@@ -7,8 +7,8 @@ Entities: 1; Documented ones: 1; With nitunits: 1; Failures: 1
 TestSuites:
 No test cases found
 Class suites: 0; Test Cases: 0; Failures: 0
-<testsuites><testsuite package="test_nitunit_md.md:1,0--15,0"><testcase classname="nitunit.&lt;file&gt;" name="test_nitunit_md.md:1,0--15,0"><system-err>Runtime error: Assert failed (.nitunit&#47;file-0.nit:8)
+<testsuites><testsuite package="test_nitunit_md.md:1,0--15,0"><testcase classname="nitunit.&lt;file&gt;" name="test_nitunit_md.md:1,0--15,0"><failure>Compilation Error</failure><system-err>Runtime error: Assert failed (.nitunit&#47;file-0.nit:8)
 </system-err><system-out>var a = 1
 assert 1 == 1
 assert false
-</system-out><error message="Runtime error"></error></testcase></testsuite></testsuites>
\ No newline at end of file
+</system-out></testcase></testsuite></testsuites>
\ No newline at end of file
index eb25a0d..afa1ac3 100644 (file)
@@ -7,4 +7,7 @@ Entities: 6; Documented ones: 5; With nitunits: 3; Failures: 3
 TestSuites:
 No test cases found
 Class suites: 0; Test Cases: 0; Failures: 0
-<testsuites><testsuite package="test_doc3::test_doc3"><testcase classname="nitunit.test_doc3::test_doc3.core::Sys" name="test_doc3::test_doc3::Sys::foo1"><failure message="test_doc3.nit:17,9--15: Syntax Error: unexpected identifier &#39;garbage&#39;."></failure></testcase><testcase classname="nitunit.test_doc3::test_doc3.core::Sys" name="test_doc3::test_doc3::Sys::foo2"><failure message="test_doc3.nit:23,4--10: Syntax Error: unexpected identifier &#39;garbage&#39;."></failure></testcase><testcase classname="nitunit.test_doc3::test_doc3.core::Sys" name="test_doc3::test_doc3::Sys::foo3"><failure message="test_doc3.nit:30,4--10: Syntax Error: unexpected identifier &#39;garbage&#39;."></failure></testcase></testsuite><testsuite></testsuite></testsuites>
\ No newline at end of file
+<testsuites><testsuite package="test_doc3::test_doc3"><testcase classname="nitunit.test_doc3::test_doc3.core::Sys" name="test_doc3::test_doc3::Sys::foo1"><failure>Compilation Error</failure><system-err>test_doc3.nit:17,9--15: Syntax Error: unexpected identifier &#39;garbage&#39;.</system-err><system-out> *garbage*
+</system-out></testcase><testcase classname="nitunit.test_doc3::test_doc3.core::Sys" name="test_doc3::test_doc3::Sys::foo2"><failure>Compilation Error</failure><system-err>test_doc3.nit:23,4--10: Syntax Error: unexpected identifier &#39;garbage&#39;.</system-err><system-out>*garbage*
+</system-out></testcase><testcase classname="nitunit.test_doc3::test_doc3.core::Sys" name="test_doc3::test_doc3::Sys::foo3"><failure>Compilation Error</failure><system-err>test_doc3.nit:30,4--10: Syntax Error: unexpected identifier &#39;garbage&#39;.</system-err><system-out>*garbage*
+</system-out></testcase></testsuite><testsuite></testsuite></testsuites>
\ No newline at end of file
index 9cbce91..27d74a9 100644 (file)
@@ -18,11 +18,11 @@ Entities: 12; Documented ones: 0; With nitunits: 0; Failures: 0
 
 TestSuites:
 Class suites: 1; Test Cases: 3; Failures: 2
-<testsuites><testsuite package="test_nitunit4&gt;"></testsuite><testsuite package="test_nitunit4::nitunit4"></testsuite><testsuite package="test_nitunit4"><testcase classname="nitunit.test_nitunit4::test_nitunit4.test_nitunit4::TestTestSuite" name="test_nitunit4::TestTestSuite::test_foo"><system-out></system-out><system-err>Before Test
+<testsuites><testsuite package="test_nitunit4&gt;"></testsuite><testsuite package="test_nitunit4::nitunit4"></testsuite><testsuite package="test_nitunit4"><testcase classname="nitunit.test_nitunit4::test_nitunit4.test_nitunit4::TestTestSuite" name="test_nitunit4::TestTestSuite::test_foo"><error>Runtime Error</error><system-err>Before Test
 Tested method
 After Test
 Runtime error: Assert failed (test_nitunit4&#47;test_nitunit4_base.nit:31)
-</system-err><error message="Runtime Error"></error></testcase><testcase classname="nitunit.test_nitunit4::test_nitunit4.test_nitunit4::TestTestSuite" name="test_nitunit4::TestTestSuite::test_bar"><system-out></system-out><system-err></system-err></testcase><testcase classname="nitunit.test_nitunit4::test_nitunit4.test_nitunit4::TestTestSuite" name="test_nitunit4::TestTestSuite::test_baz"><system-out></system-out><system-err>Diff
+</system-err></testcase><testcase classname="nitunit.test_nitunit4::test_nitunit4.test_nitunit4::TestTestSuite" name="test_nitunit4::TestTestSuite::test_bar"></testcase><testcase classname="nitunit.test_nitunit4::test_nitunit4.test_nitunit4::TestTestSuite" name="test_nitunit4::TestTestSuite::test_baz"><error>Runtime Error</error><system-err>Diff
 --- expected:test_nitunit4&#47;test_nitunit4.sav&#47;test_baz.res
 +++ got:.nitunit&#47;gen_test_nitunit4_test_baz.out1
 @@ -1 +1,3 @@
@@ -30,4 +30,4 @@ Runtime error: Assert failed (test_nitunit4&#47;test_nitunit4_base.nit:31)
 +Before Test
 +Tested method
 +After Test
-</system-err><error message="Runtime Error"></error></testcase></testsuite><testsuite package="test_nitunit4::test_nitunit4"></testsuite><testsuite></testsuite><testsuite package="test_nitunit4::test_nitunit4_base"></testsuite><testsuite></testsuite></testsuites>
\ No newline at end of file
+</system-err></testcase></testsuite><testsuite package="test_nitunit4::test_nitunit4"></testsuite><testsuite></testsuite><testsuite package="test_nitunit4::test_nitunit4_base"></testsuite><testsuite></testsuite></testsuites>
\ No newline at end of file