X-Git-Url: http://nitlanguage.org diff --git a/src/nitunit.nit b/src/nitunit.nit index e0ad3e1..e86f92f 100644 --- a/src/nitunit.nit +++ b/src/nitunit.nit @@ -12,266 +12,97 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Program to extract and execute unit tests from nit source files +# Testing tool. +# see `testing/README` module nitunit -import modelize_property -intrude import markdown -import parser_util +import testing -# Extractor, Executor an Reporter for the tests in a module -class NitUnitExecutor - super Doc2Mdwn - - # The name of the module to import - var modname: String +var toolcontext = new ToolContext - # The prefix of the generated Nit source-file - var prefix: String +toolcontext.option_context.add_option(toolcontext.opt_full, toolcontext.opt_output, toolcontext.opt_dir, toolcontext.opt_noact, toolcontext.opt_pattern, toolcontext.opt_file, toolcontext.opt_gen_unit, toolcontext.opt_gen_force, toolcontext.opt_gen_private, toolcontext.opt_gen_show) +toolcontext.tooldescription = "Usage: nitunit [OPTION]... ...\nExecutes the unit tests from Nit source files." - # The XML node associated to the module - var testsuite: HTMLTag +toolcontext.process_options(args) +var args = toolcontext.option_context.rest - # Initialize a new e - init(toolcontext: ToolContext, prefix: String, modname: String, testsuite: HTMLTag) - do - super(toolcontext) - self.prefix = prefix - self.modname = modname - self.testsuite = testsuite +if toolcontext.opt_gen_unit.value then + if toolcontext.opt_pattern.value != null then + print "Option --pattern cannot be used with --gen-suite" + exit(0) end - - # All blocks of code from a same `ADoc` - var block = new Array[String] - - redef fun process_code(n: HTMLTag, text: String) - do - # Try to parse it - var ast = toolcontext.parse_something(text) - - # We want executable code - if not (ast isa AModule or ast isa ABlockExpr or ast isa AExpr) then return - - # Search `assert` in the AST - var v = new SearchAssertVisitor - v.enter_visit(ast) - if not v.foundit then return - - # Add it to the file - block.add(text) + if toolcontext.opt_file.value != null then + print "Option --target-file cannot be used with --gen-suite" + exit(0) end - - # used to generate distinct names - var cpt = 0 - - # The entry point for a new `ndoc` node - # Fill the prepated `tc` (testcase) XTM node - fun extract(ndoc: ADoc, tc: HTMLTag) - do - block.clear - - work(ndoc.to_mdoc) - - if block.is_empty then return - - toolcontext.modelbuilder.unit_entities += 1 - - cpt += 1 - var file = "{prefix}{cpt}.nit" - - toolcontext.info("Execute {tc.attrs["classname"]}.{tc.attrs["name"]} in {file}", 2) - - var dir = file.dirname - if dir != "" then dir.mkdir - var f - f = new OFStream.open(file) - f.write("# GENERATED FILE\n") - f.write("# Example extracted from a documentation\n") - var modname = self.modname - f.write("import {modname}\n") - f.write("\n") - for text in block do - f.write(text) - end - f.close - - if toolcontext.opt_noact.value then return - - var nit_dir = toolcontext.nit_dir - var nitg = "{nit_dir}/bin/nitg" - if nit_dir == null or not nitg.file_exists then - toolcontext.error(null, "Cannot find nitg. Set envvar NIT_DIR.") - toolcontext.check_errors - end - var cmd = "{nitg} --ignore-visibility --no-color '{file}' -I . >'{file}.out1' 2>&1 >'{file}.out1' 2>&1 ") - tc.attr("name", "") - d2m.extract(ndoc, tc) - end label x - for nclassdef in nmodule.n_classdefs do - var mclassdef = nclassdef.mclassdef.as(not null) - if nclassdef isa AStdClassdef then - total_entities += 1 - var ndoc = nclassdef.n_doc - if ndoc != null then - doc_entities += 1 - tc = new HTMLTag("testcase") - tc.attr("classname", mmodule.full_name + "." + mclassdef.mclass.full_name) - tc.attr("name", "") - d2m.extract(ndoc, tc) - end - end - for npropdef in nclassdef.n_propdefs do - var mpropdef = npropdef.mpropdef.as(not null) - total_entities += 1 - var ndoc = npropdef.n_doc - if ndoc != null then - doc_entities += 1 - tc = new HTMLTag("testcase") - tc.attr("classname", mmodule.full_name + "." + mclassdef.mclass.full_name) - tc.attr("name", mpropdef.mproperty.full_name) - d2m.extract(ndoc, tc) - end - end - end +if toolcontext.opt_full.value then mmodules = model.mmodules - return ts +for a in args do + if not a.file_exists then + toolcontext.fatal_error(null, "Error: cannot load file or module `{a}`.") end + # Try to load the file as a markdown document + var mdoc = modelbuilder.load_markdown(a) + page.add modelbuilder.test_mdoc(mdoc) end -redef class ToolContext - var opt_full = new OptionBool("Process also imported modules", "--full") - var opt_output = new OptionString("Output name (default is 'nitunit.xml')", "-o", "--output") - var opt_dir = new OptionString("Working directory (default is '.nitunit')", "--dir") - var opt_noact = new OptionBool("Does not compile and run tests", "--no-act") +for a in module_files do + var g = modelbuilder.get_mgroup(a) + if g == null then continue + page.add modelbuilder.test_group(g) end -var toolcontext = new ToolContext - -toolcontext.option_context.add_option(toolcontext.opt_full, toolcontext.opt_output, toolcontext.opt_dir, toolcontext.opt_noact) -toolcontext.tooldescription = "Usage: nitunit [OPTION]... ...\nExecutes the unit tests from Nit source files." - -toolcontext.process_options(args) -var args = toolcontext.option_context.rest - -var model = new Model -var modelbuilder = new ModelBuilder(model, toolcontext) - -var mmodules = modelbuilder.parse(args) -modelbuilder.run_phases - -var page = new HTMLTag("testsuites") - -if toolcontext.opt_full.value then mmodules = model.mmodules - for m in mmodules do page.add modelbuilder.test_markdown(m) + page.add modelbuilder.test_unit(m) end var file = toolcontext.opt_output.value if file == null then file = "nitunit.xml" page.write_to_file(file) -print "Results saved in {file}" - +# print docunits results +print "DocUnits:" if modelbuilder.unit_entities == 0 then - print "No nitunits found" + print "No doc units found" else if modelbuilder.failed_entities == 0 and not toolcontext.opt_noact.value then - print "Success" + print "DocUnits Success" end print "Entities: {modelbuilder.total_entities}; Documented ones: {modelbuilder.doc_entities}; With nitunits: {modelbuilder.unit_entities}; Failures: {modelbuilder.failed_entities}" +# print testsuites results +print "\nTestSuites:" +if modelbuilder.total_tests == 0 then + print "No test cases found" +else if modelbuilder.failed_tests == 0 and not toolcontext.opt_noact.value then + print "TestSuites Success" +end +print "Class suites: {modelbuilder.total_classes}; Test Cases: {modelbuilder.total_tests}; Failures: {modelbuilder.failed_tests}"