import testing_base
import html
private import parse_annotations
-private import annotation
private import realtime
redef class ToolContext
var toolcontext = mbuilder.toolcontext
var suite = new TestSuite(mmodule, toolcontext)
# method to execute before all tests in the module
- var before_module = mmodule.before_test
- if before_module != null then
+ for mmethod in mmodule.before_all do
toolcontext.modelbuilder.total_tests += 1
- suite.before_module = new TestCase(suite, before_module, toolcontext)
+ suite.before_all.add new TestCase(suite, mmethod, toolcontext)
end
# generate all test cases
for mclassdef in mmodule.mclassdefs do
if not mclassdef.is_test then continue
if not suite_match_pattern(mclassdef) then continue
toolcontext.modelbuilder.total_classes += 1
+
+ var before = mclassdef.before
+ var after = mclassdef.after
+
for mpropdef in mclassdef.mpropdefs do
if not mpropdef isa MMethodDef or not mpropdef.is_test then continue
if not case_match_pattern(mpropdef) then continue
toolcontext.modelbuilder.total_tests += 1
var test = new TestCase(suite, mpropdef, toolcontext)
- suite.add_test test
+ test.before = before
+ test.after = after
+ suite.test_cases.add test
end
end
# method to execute after all tests in the module
- var after_module = mmodule.after_test
- if after_module != null then
+ for mmethod in mmodule.after_all do
toolcontext.modelbuilder.total_tests += 1
- suite.after_module = new TestCase(suite, after_module, toolcontext)
+ suite.after_all.add new TestCase(suite, mmethod, toolcontext)
end
suite.run
return suite
# List of `TestCase` to be executed in this suite.
var test_cases = new Array[TestCase]
- # Add a `TestCase` to the suite.
- fun add_test(case: TestCase) do test_cases.add case
-
- # Test to be executed before the whole test suite.
- var before_module: nullable TestCase = null
+ # Tests to be executed before the whole test suite.
+ var before_all = new Array[TestCase]
- # Test to be executed after the whole test suite.
- var after_module: nullable TestCase = null
+ # Tests to be executed after the whole test suite.
+ var after_all = new Array[TestCase]
# Display test suite status in std-out.
fun show_status do
var test_cases = self.test_cases.to_a
- if before_module != null then test_cases.add before_module.as(not null)
- if after_module != null then test_cases.add after_module.as(not null)
+ test_cases.add_all before_all
+ test_cases.add_all after_all
toolcontext.show_unit_status("Test-suite of module " + mmodule.full_name, test_cases)
end
end
toolcontext.info("Execute test-suite {mmodule.name}", 1)
- var before_module = self.before_module
- var after_module = self.after_module
-
- if before_module != null then
+ for before_module in before_all do
before_module.run
toolcontext.clear_progress_bar
toolcontext.show_unit(before_module)
toolcontext.clear_progress_bar
toolcontext.show_unit(case)
end
- if after_module != null then
+ for after_module in after_all do
after_module.fail "Nitunit Error: before_module test failed"
toolcontext.clear_progress_bar
toolcontext.show_unit(after_module)
show_status
end
- if not after_module == null then
+ for after_module in after_all do
after_module.run
toolcontext.clear_progress_bar
toolcontext.show_unit(after_module)
# Write the test unit for `self` in a nit compilable file.
fun write_to_nit do
var file = new Template
- file.addn "intrude import test_suite"
+ file.addn "intrude import core"
file.addn "import {mmodule.name}\n"
file.addn "var name = args.first"
- var before_module = self.before_module
- if before_module != null then
+ for before_module in before_all do
before_module.write_to_nit(file)
end
for case in test_cases do
case.write_to_nit(file)
end
- var after_module = self.after_module
- if after_module != null then
+ for after_module in after_all do
after_module.write_to_nit(file)
end
file.write_to_file("{test_file}.nit")
# Test method to be compiled and tested.
var test_method: MMethodDef
+ # Cases to execute before this one
+ var before = new Array[MMethodDef]
+
+ # Cases to execute after this one
+ var after = new Array[MMethodDef]
+
redef fun full_name do return test_method.full_name
redef fun location do return test_method.location
if test_method.mproperty.is_toplevel then
file.addn "\t{name}"
else
- file.addn "\tvar subject = new {test_method.mclassdef.name}.nitunit"
- file.addn "\tsubject.before_test"
+ file.addn "\tvar subject = new {test_method.mclassdef.name}.intern"
+ for mmethod in before do
+ file.addn "\tsubject.{mmethod.name}"
+ end
file.addn "\tsubject.{name}"
- file.addn "\tsubject.after_test"
+ for mmethod in after do
+ file.addn "\tsubject.{mmethod.name}"
+ end
end
file.addn "end"
end
end
end
-redef class MMethodDef
- # TODO use annotations?
-
- # Is the method a test_method?
- # i.e. begins with "test_"
- private fun is_test: Bool do return name.has_prefix("test_")
+redef class MClassDef
+ # Methods tagged with `before` in this class definition
+ private fun before: Array[MMethodDef] do
+ var res = new Array[MMethodDef]
+ for mpropdef in mpropdefs do
+ if mpropdef isa MMethodDef and mpropdef.is_before then
+ res.add mpropdef
+ end
+ end
+ var in_hierarchy = self.in_hierarchy
+ if in_hierarchy == null then return res
+ for mclassdef in in_hierarchy.direct_greaters do
+ res.add_all mclassdef.before
+ end
+ return res
+ end
- # Is the method a "before_module"?
- private fun is_before_module: Bool do return name == "before_module"
+ # Methods tagged with `before_all` in this class definition
+ private fun before_all: Array[MMethodDef] do
+ var res = new Array[MMethodDef]
+ for mpropdef in mpropdefs do
+ if mpropdef isa MMethodDef and mpropdef.is_before_all then
+ res.add mpropdef
+ end
+ end
+ var in_hierarchy = self.in_hierarchy
+ if in_hierarchy == null then return res
+ for mclassdef in in_hierarchy.direct_greaters do
+ res.add_all mclassdef.before_all
+ end
+ return res
+ end
- # Is the method a "after_module"?
- private fun is_after_module: Bool do return name == "after_module"
-end
+ # Methods tagged with `after` in this class definition
+ private fun after: Array[MMethodDef] do
+ var res = new Array[MMethodDef]
+ for mpropdef in mpropdefs do
+ if mpropdef isa MMethodDef and mpropdef.is_after then
+ res.add mpropdef
+ end
+ end
+ var in_hierarchy = self.in_hierarchy
+ if in_hierarchy == null then return res
+ for mclassdef in in_hierarchy.direct_greaters do
+ res.add_all mclassdef.after
+ end
+ return res
+ end
-redef class MClassDef
- # Is the class a TestClass?
- # i.e. is a subclass of `TestSuite`
- private fun is_test: Bool do
+ # Methods tagged with `after_all` in this class definition
+ private fun after_all: Array[MMethodDef] do
+ var res = new Array[MMethodDef]
+ for mpropdef in mpropdefs do
+ if mpropdef isa MMethodDef and mpropdef.is_after_all then
+ res.add mpropdef
+ end
+ end
var in_hierarchy = self.in_hierarchy
- if in_hierarchy == null then return false
- for sup in in_hierarchy.greaters do
- if sup.name == "TestSuite" then return true
+ if in_hierarchy == null then return res
+ for mclassdef in in_hierarchy.direct_greaters do
+ res.add_all mclassdef.after_all
end
- return false
+ return res
end
end
redef class MModule
- # "before_module" method for this module.
- private fun before_test: nullable MMethodDef do
- for mclassdef in mclassdefs do
- if not mclassdef.name == "Sys" then continue
- for mpropdef in mclassdef.mpropdefs do
- if mpropdef isa MMethodDef and mpropdef.is_before_module then return mpropdef
+ # Methods tagged with `before_all` at the module level (in `Sys`)
+ private fun before_all: Array[MMethodDef] do
+ var res = new Array[MMethodDef]
+ for mmodule in in_importation.greaters do
+ for mclassdef in mmodule.mclassdefs do
+ if mclassdef.name != "Sys" then continue
+ for mpropdef in mclassdef.mpropdefs do
+ if not mpropdef isa MMethodDef or not mpropdef.is_before_all then continue
+ res.add mpropdef
+ end
end
end
- return null
+ return res
end
- # "after_module" method for this module.
- private fun after_test: nullable MMethodDef do
- for mclassdef in mclassdefs do
- if not mclassdef.name == "Sys" then continue
- for mpropdef in mclassdef.mpropdefs do
- if mpropdef isa MMethodDef and mpropdef.is_after_module then return mpropdef
+ # Methods tagged with `after_all` at the module level (in `Sys`)
+ private fun after_all: Array[MMethodDef] do
+ var res = new Array[MMethodDef]
+ for mmodule in in_importation.greaters do
+ for mclassdef in mmodule.mclassdefs do
+ if mclassdef.name != "Sys" then continue
+ for mpropdef in mclassdef.mpropdefs do
+ if not mpropdef isa MMethodDef or not mpropdef.is_after_all then continue
+ res.add mpropdef
+ end
end
end
- return null
+ return res
end
end