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 transform output
For any functionality that we want to work (ie test), there are actually three tests, with the _same_ name
One in each of the parser/transform/ast classes
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
Test are grouped by functionality into cases and define methods parse_*
Test cases must include ParserHelper, which includes the magic to write the 3 test methods for each
parse method. See test_basic ofr easy example.

View File

@ -1,29 +1,59 @@
require_relative "../helper"
module ParserTest
# Included in parser test will create tests methods
module ParserHelper
def setup
@parser = Parser::Composed.new
@transform = Parser::Transform.new
def self.included(base)
base.send :include, InstanceMethods #provides helpers and setup
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
def check_parse
is = @parser.parse(@input)
#puts is.inspect
assert_equal @parse_output , is
end
def check_transform
is = @transform.apply @parse_output
#puts is.transform
assert_equal @transform_output , is
end
def check_ast
syntax = @parser.parse(@input)
tree = @transform.apply(syntax)
# puts tree.inspect
assert_equal @transform_output , tree
end
end
module ClassMethods
# this creates test methods dynamically. For each parse_* method we create
# three test_* methods that in turn check the three phases.
# runnable_methods is called by minitest to determine which tests to run (ie normally test_*)
def 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
end
end

View File

@ -1,40 +1,25 @@
require_relative "helper"
class TestBasic < MiniTest::Test
include ParserTest
# 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
# include the magic (setup and parse -> test method translation), see there
include ParserHelper
def parse_number
@input = '42 '
@string_input = '42 '
@parse_output = {:integer => '42'}
@transform_output = Parser::IntegerExpression.new(42)
@parser = @parser.integer
end
def parse_name
@input = 'foo '
@string_input = 'foo '
@parse_output = {:name => 'foo'}
@transform_output = Parser::NameExpression.new('foo')
@parser = @parser.name
end
def parse_string
@input = <<HERE
@string_input = <<HERE
"hello"
HERE
@parse_output = {:string=>"hello"}