adds the concern aproach and explanation

This commit is contained in:
Torsten Ruger 2014-04-29 14:09:10 +03:00
parent b6e08faa39
commit 585c27c78d
3 changed files with 63 additions and 62 deletions

View File

@ -14,20 +14,6 @@ Each test must thus specify (as instance variables):
- the parse output - the parse output
- the transform output - the transform output
Test are grouped by functionality into cases and define methods parse_*
For any functionality that we want to work (ie test), there are actually three tests, with the _same_ name Test cases must include ParserHelper, which includes the magic to write the 3 test methods for each
One in each of the parser/transform/ast classes parse method. See test_basic ofr easy example.
Parser test that the parser parses and thet the output is correct. Rules are named and and boil down to
hashes and arrays with lots of symbols for the names the rules (actually the reults) were given
Transform test really just test the tranformation. They basically take the output of the parse
and check that correct Ast classes are produced
Ast tests both steps in one. Ie string input to ast classes output
All threee classes are layed out quite similarly in that they use a check method and
each test assigns @input and @expected which the check methods then checks
The check methods have a pust in it (to be left) which is very handy for checking
also the output of parser.check can actually be used as the input of transform
Repeat: For every test in parser, there should be one in transform and ast
The test in transform should use the output of parser as input
The test in ast should expect the same result as transform

View File

@ -1,29 +1,59 @@
require_relative "../helper" require_relative "../helper"
module ParserTest # Included in parser test will create tests methods
module ParserHelper
def setup def self.included(base)
@parser = Parser::Composed.new base.send :include, InstanceMethods #provides helpers and setup
@transform = Parser::Transform.new base.send :extend, ClassMethods #gets the method creation going
end
module InstanceMethods
def setup
@parser = Parser::Composed.new
@transform = Parser::Transform.new
end
# check that @string_input parses correctly to @parse_output
def check_parse
is = @parser.parse(@string_input)
#puts is.inspect
assert_equal @parse_output , is
end
#check that @parse_output transforms to @transform_output
def check_transform
is = @transform.apply @parse_output
#puts is.transform
assert_equal @transform_output , is
end
# check that @string_input parses and transforms to @transform_output
def check_ast
syntax = @parser.parse(@string_input)
tree = @transform.apply(syntax)
# puts tree.inspect
assert_equal @transform_output , tree
end
end end
def check_parse module ClassMethods
is = @parser.parse(@input) # this creates test methods dynamically. For each parse_* method we create
#puts is.inspect # three test_* methods that in turn check the three phases.
assert_equal @parse_output , is # runnable_methods is called by minitest to determine which tests to run (ie normally test_*)
end def runnable_methods
tests = []
def check_transform public_instance_methods(true).grep(/^parse_/).map(&:to_s).each do |parse|
is = @transform.apply @parse_output ["ast" , "transform" , "parse"].each do |what|
#puts is.transform name = "parse_#{what}"
assert_equal @transform_output , is tests << name
end self.send(:define_method, name ) do
send(parse)
def check_ast send("check_#{what}")
syntax = @parser.parse(@input) end
tree = @transform.apply(syntax) end
# puts tree.inspect end
assert_equal @transform_output , tree tests
end end
end
end end

View File

@ -1,40 +1,25 @@
require_relative "helper" require_relative "helper"
class TestBasic < MiniTest::Test class TestBasic < MiniTest::Test
include ParserTest # include the magic (setup and parse -> test method translation), see there
include ParserHelper
# this creates test methods dynamically , one for each file in runners directory
def self.runnable_methods
tests = []
public_instance_methods(true).grep(/^parse_/).map(&:to_s).each do |parse|
["ast" , "transform" , "parse"].each do |what|
name = "parse_#{what}"
tests << name
self.send(:define_method, name ) do
send(parse)
send("check_#{what}")
end
end
end
tests
end
def parse_number def parse_number
@input = '42 ' @string_input = '42 '
@parse_output = {:integer => '42'} @parse_output = {:integer => '42'}
@transform_output = Parser::IntegerExpression.new(42) @transform_output = Parser::IntegerExpression.new(42)
@parser = @parser.integer @parser = @parser.integer
end end
def parse_name def parse_name
@input = 'foo ' @string_input = 'foo '
@parse_output = {:name => 'foo'} @parse_output = {:name => 'foo'}
@transform_output = Parser::NameExpression.new('foo') @transform_output = Parser::NameExpression.new('foo')
@parser = @parser.name @parser = @parser.name
end end
def parse_string def parse_string
@input = <<HERE @string_input = <<HERE
"hello" "hello"
HERE HERE
@parse_output = {:string=>"hello"} @parse_output = {:string=>"hello"}