# This file is part of NIT ( http://www.nitlanguage.org ). # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 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 module nitunit import modelize_property intrude import markdown import parser_util # Extractor, Executor an Reporter for the tests in a module class NitUnitExecutor super Doc2Mdwn # The name of the module to import var modname: String # The prefix of the generated Nit source-file var prefix: String # The XML node associated to the module var testsuite: HTMLTag # 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 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) 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 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 var cmd = "../bin/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 var ndoc = nclassdef.n_doc if ndoc != null then 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) var ndoc = npropdef.n_doc if ndoc != null then 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 return ts end 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") end var toolcontext = new ToolContext toolcontext.option_context.add_option(toolcontext.opt_full, toolcontext.opt_output, toolcontext.opt_dir) 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) end var file = toolcontext.opt_output.value if file == null then file = "nitunit.xml" page.write_to_file(file)