X-Git-Url: http://nitlanguage.org diff --git a/src/testing/testing_doc.nit b/src/testing/testing_doc.nit index 7d4afe6..7419c9f 100644 --- a/src/testing/testing_doc.nit +++ b/src/testing/testing_doc.nit @@ -15,12 +15,17 @@ # Testing from code comments. module testing_doc +private import parser_util import testing_base -intrude import docdown +import markdown +import html # Extractor, Executor and Reporter for the tests in a module class NitUnitExecutor - super Doc2Mdwn + super HTMLDecorator + + # Toolcontext used to parse Nit code blocks. + var toolcontext: ToolContext # The prefix of the generated Nit source-file var prefix: String @@ -31,45 +36,14 @@ class NitUnitExecutor # The XML node associated to the module var testsuite: HTMLTag - # All blocks of code from a same `ADoc` - var blocks = new Array[Array[String]] - - # All failures from a same `ADoc` - var failures = new Array[String] - - redef fun process_code(n: HTMLTag, text: String, tag: nullable String) - do - # Skip non-blocks - if n.tag != "pre" then return - - # Skip strict non-nit - if tag != null and tag != "nit" and tag != "" then - return - end - - # Try to parse it - var ast = toolcontext.parse_something(text) - - # Skip pure comments - if ast isa TComment then return - - # We want executable code - if not (ast isa AModule or ast isa ABlockExpr or ast isa AExpr) then - var message = "" - if ast isa AError then message = " At {ast.location}: {ast.message}." - toolcontext.warning(mdoc.location, "invalid-block", "Error: there is a block of invalid Nit code, thus not considered a nitunit. To suppress this warning, enclose the block with a fence tagged `nitish` or `raw` (see `man nitdoc`).{message}") - failures.add("{mdoc.location}: Invalid block of code.{message}") - return - end + # The name of the suite + var name: String - # Create a first block - # Or create a new block for modules that are more than a main part - if blocks.is_empty or ast isa AModule then - blocks.add(new Array[String]) - end + # Markdown processor used to parse markdown comments and extract code. + var mdproc = new MarkdownProcessor - # Add it to the file - blocks.last.add(text) + init do + mdproc.emitter.decorator = new NitunitDecorator(self) end # The associated documentation object @@ -78,46 +52,48 @@ class NitUnitExecutor # used to generate distinct names var cpt = 0 - # The entry point for a new `ndoc` node - # Fill `docunits` with new discovered unit of tests. + # The last docunit extracted from a mdoc. # - # `tc` (testcase) is the pre-filled XML node - fun extract(mdoc: MDoc, tc: HTMLTag) - do - blocks.clear - failures.clear - - self.mdoc = mdoc + # Is used because a new code-block might just be added to it. + var last_docunit: nullable DocUnit = null - work(mdoc) + var xml_classname: String is noautoinit - toolcontext.check_errors + var xml_name: String is noautoinit - 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.failed_entities += 1 - end - if blocks.is_empty then testsuite.add(tc) - end + # The entry point for a new `ndoc` node + # Fill `docunits` with new discovered unit of tests. + fun extract(mdoc: MDoc, xml_classname, xml_name: String) + do + last_docunit = null + self.xml_classname = xml_classname + self.xml_name = xml_name - if blocks.is_empty then return + self.mdoc = mdoc - for block in blocks do - docunits.add new DocUnit(mdoc, tc, block.join("")) - end + # Populate `blocks` from the markdown decorator + mdproc.process(mdoc.content.join("\n")) end # All extracted docunits var docunits = new Array[DocUnit] + fun mark_done(du: DocUnit) + do + du.is_done = true + end + # Execute all the docunits fun run_tests do var simple_du = new Array[DocUnit] for du in docunits do + # Skip existing errors + if du.error != null then + mark_done(du) + continue + end + var ast = toolcontext.parse_something(du.block) if ast isa AExpr then simple_du.add du @@ -127,6 +103,14 @@ class NitUnitExecutor end 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 # Executes multiples doc-units in a shared program. @@ -150,7 +134,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 @@ -175,34 +159,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) - var res2 = sys.system("{file.to_program_name}.bin {i} >>'{file}.out1' 2>&1 '{file}.out1' 2>&1 >'{file}.out1' 2>&1 '{file}.out1' 2>&1 '{file}.out1' 2>&1 ") - tc.attr("name", "") - d2m.extract(ndoc.to_mdoc, tc) + d2m.extract(ndoc.to_mdoc, "nitunit." + mmodule.full_name + ".", "") end label x for nclassdef in nmodule.n_classdefs do var mclassdef = nclassdef.mclassdef @@ -379,10 +476,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", "") - d2m.extract(ndoc.to_mdoc, tc) + d2m.extract(ndoc.to_mdoc, "nitunit." + mmodule.full_name + "." + mclassdef.mclass.full_name, "") end end for npropdef in nclassdef.n_propdefs do @@ -392,10 +486,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 @@ -419,20 +510,15 @@ redef class ModelBuilder var prefix = toolcontext.test_dir prefix = prefix.join_path(mgroup.to_s) - var d2m = new NitUnitExecutor(toolcontext, prefix, o, ts) - - var tc + var d2m = new NitUnitExecutor(toolcontext, prefix, o, ts, "Docunits of group {mgroup.full_name}") 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", "") - d2m.extract(mdoc, tc) + d2m.extract(mdoc, "nitunit." + mgroup.full_name, "") d2m.run_tests @@ -450,19 +536,13 @@ redef class ModelBuilder ts.attr("package", file) var prefix = toolcontext.test_dir / "file" - var d2m = new NitUnitExecutor(toolcontext, prefix, null, ts) - - var tc + var d2m = new NitUnitExecutor(toolcontext, prefix, null, ts, "Docunits of file {file}") total_entities += 1 doc_entities += 1 - tc = new HTMLTag("testcase") # NOTE: jenkins expects a '.' in the classname attr - tc.attr("classname", "nitunit.") - tc.attr("name", file) - - d2m.extract(mdoc, tc) + d2m.extract(mdoc, "nitunit.", file) d2m.run_tests return ts