From: Jean Privat Date: Sat, 17 Aug 2013 03:56:51 +0000 (-0400) Subject: tool: new program nitunit.nit X-Git-Tag: v0.6.1~29^2~5 X-Git-Url: http://nitlanguage.org?hp=213dcff09c2105a1639cadff0ddc1f974387eacd tool: new program nitunit.nit Signed-off-by: Jean Privat --- diff --git a/src/nitunit.nit b/src/nitunit.nit new file mode 100644 index 0000000..f31b405 --- /dev/null +++ b/src/nitunit.nit @@ -0,0 +1,248 @@ +# 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 + + var toolcontext: ToolContext + + # 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 + self.toolcontext = 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) + + 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 --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 + 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.process_options +var args = toolcontext.option_context.rest +if args.is_empty or toolcontext.opt_help.value then + print "usage: nitunit [options] file.nit..." + toolcontext.option_context.usage + return +end + +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.save(file)