testml 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. data/.gemspec +3 -1
  2. data/CHANGELOG.yaml +4 -1
  3. data/LICENSE +1 -1
  4. data/README.rdoc +30 -5
  5. data/Rakefile +10 -1
  6. data/ToDo +56 -0
  7. data/lib/rake/testml.rb +14 -0
  8. data/lib/testml.rb +46 -2
  9. data/lib/testml/bridge.rb +5 -0
  10. data/lib/testml/compiler.rb +106 -0
  11. data/lib/testml/compiler/lite.rb +194 -0
  12. data/lib/testml/compiler/pegex.rb +50 -0
  13. data/lib/testml/compiler/pegex/ast.rb +145 -0
  14. data/lib/testml/compiler/pegex/grammar.rb +173 -0
  15. data/lib/testml/library.rb +7 -0
  16. data/lib/testml/library/debug.rb +18 -0
  17. data/lib/testml/library/standard.rb +86 -0
  18. data/lib/testml/runtime.rb +501 -0
  19. data/lib/testml/runtime/unit.rb +94 -0
  20. data/lib/testml/setup.rb +65 -0
  21. data/lib/testml/util.rb +22 -0
  22. data/test/ast/arguments.tml +87 -0
  23. data/test/ast/basic.tml +83 -0
  24. data/test/ast/dataless.tml +36 -0
  25. data/test/ast/exceptions.tml +59 -0
  26. data/test/ast/external.tml +42 -0
  27. data/test/ast/function.tml +276 -0
  28. data/test/ast/label.tml +58 -0
  29. data/test/ast/markers.tml +36 -0
  30. data/test/ast/semicolons.tml +30 -0
  31. data/test/ast/truth.tml +85 -0
  32. data/test/ast/types.tml +163 -0
  33. data/test/compile-lite.rb +38 -0
  34. data/test/compile-testml-document.rb +59 -0
  35. data/test/compile.rb +57 -0
  36. data/test/inline-bridge.rb +30 -0
  37. data/test/inline.rb +28 -0
  38. data/test/strings.rb +24 -0
  39. data/test/testml.rb +38 -0
  40. data/test/testml.yaml +10 -0
  41. data/test/testml/arguments.tml +18 -0
  42. data/test/testml/assertions.tml +15 -0
  43. data/test/testml/basic.tml +37 -0
  44. data/test/testml/dataless.tml +9 -0
  45. data/test/testml/exceptions.tml +16 -0
  46. data/test/testml/external.tml +8 -0
  47. data/test/testml/external1.tml +10 -0
  48. data/test/testml/external2.tml +3 -0
  49. data/test/testml/function.tml +82 -0
  50. data/test/testml/label.tml +24 -0
  51. data/test/testml/markers.tml +19 -0
  52. data/test/testml/semicolons.tml +10 -0
  53. data/test/testml/standard.tml +50 -0
  54. data/test/testml/truth.tml +22 -0
  55. data/test/testml/types.tml +24 -0
  56. data/test/testml_bridge.rb +28 -0
  57. metadata +69 -4
  58. data/test/fail.rb +0 -12
@@ -0,0 +1,94 @@
1
+ require 'test/unit'
2
+ require 'testml/runtime'
3
+
4
+ # This is the class that Test::Unit will use to run actual tests. Every time
5
+ # that a test file creates a TestML object, we inject a method called
6
+ # "test_#{test_file_name}" into this class, since we know that Test::Unit
7
+ # calls methods that begin with 'test'.
8
+ class TestML::TestCase < Test::Unit::TestCase
9
+ attr_accessor :name
10
+ end
11
+
12
+ class TestML::Runtime::Unit < TestML::Runtime
13
+ attr_accessor :testcase
14
+ attr_accessor :planned
15
+
16
+ def run(unittest_testcase)
17
+ @testcase = unittest_testcase
18
+ @planned = false
19
+ super()
20
+ check_plan
21
+ plan_end
22
+ end
23
+
24
+ def run_assertion(*args)
25
+ check_plan
26
+ super(*args)
27
+ end
28
+
29
+ def check_plan
30
+ if ! @planned
31
+ title
32
+ plan_begin
33
+ @planned = true
34
+ end
35
+ end
36
+
37
+ # XXX Need to disable by default and provide a simple way to turn on.
38
+ def title
39
+ if title = @function.getvar('Title')
40
+ title = title.value
41
+ title = "\n=== #{title} ===\n"
42
+ # TODO Figure out when to print titles.
43
+ # STDERR.write title
44
+ end
45
+ end
46
+
47
+ def skip_test(reason)
48
+ fail "TODO"
49
+ end
50
+
51
+ def plan_begin;end
52
+
53
+ def plan_end
54
+ if plan = @function.getvar('Plan')
55
+ count = @function.getvar('TestNumber').value
56
+ testcase.assert_equal plan.value.to_i, count, 'Tests Planned'
57
+ end
58
+ end
59
+
60
+ def assert_EQ(got, want)
61
+ got = got.value
62
+ want = want.value
63
+ # TODO Move this logic to testml/diff
64
+ if got != want
65
+ if want.match /\n/
66
+ File.open('/tmp/got', 'w') {|f| f.write got}
67
+ File.open('/tmp/want', 'w') {|f| f.write want}
68
+ STDERR.write(`diff -u /tmp/want /tmp/got`)
69
+ end
70
+ end
71
+ testcase.assert_equal want, got, get_label
72
+ end
73
+
74
+ def assert_HAS(got, has)
75
+ got = got.value
76
+ has = has.value
77
+ assertion = got.index(has)
78
+ if !assertion
79
+ msg = <<"..."
80
+ Failed TestML HAS (~~) assertion. This text:
81
+ '#{got}'
82
+ does not contain this string:
83
+ '#{has}'
84
+ ...
85
+ STDERR.write(msg)
86
+ end
87
+ testcase.assert(assertion, get_label)
88
+ end
89
+
90
+ def assert_OK(got)
91
+ testcase.assert(got.bool.value, get_label)
92
+ end
93
+
94
+ end
@@ -0,0 +1,65 @@
1
+ require 'rake'
2
+ require 'yaml'
3
+ require 'pathname'
4
+ include FileUtils
5
+
6
+ DEFAULT_TESTML_CONF = './test/testml.yaml'
7
+
8
+ class TestML; end
9
+ class TestML::Setup
10
+ def setup(testml_conf)
11
+ testml_conf ||= DEFAULT_TESTML_CONF
12
+ fail "TestML conf file '#{testml_conf}' not found" \
13
+ unless File.exists? testml_conf
14
+ fail "TestML conf file must be .yaml" \
15
+ unless testml_conf.match /\.ya?ml$/
16
+ # File paths are relative to the yaml file location
17
+ base = File.dirname testml_conf
18
+ conf = YAML.load File.read testml_conf
19
+ source = conf['source_testml_dir'] \
20
+ or fail "`rake testml` requires 'source_testml_dir' key in '#{testml_conf}'"
21
+ target = conf['local_testml_dir'] \
22
+ or fail "`rake testml` requires 'local_testml_dir' key in '#{testml_conf}'"
23
+ tests = conf['test_file_dir'] || '.'
24
+ source = File.expand_path source, base
25
+ target = File.expand_path target, base
26
+ tests = File.expand_path tests, base
27
+ fail "'#{source}' directory does not exist" \
28
+ unless Dir.exists? source
29
+ mkdir target unless Dir.exists? target
30
+ mkdir tests unless Dir.exists? tests
31
+ template = conf['test_file_template']
32
+ skip = conf['exclude_testml_files'] || []
33
+ files = conf['include_testml_files'] ||
34
+ Dir.new(source).grep(/\.tml$/)
35
+ files.sort.each do |file|
36
+ next if skip.include? file
37
+ s = "#{source}/#{file}"
38
+ t = "#{target}/#{file}"
39
+ if ! uptodate?(t, [s])
40
+ puts "Copying #{rel(s)} to #{rel(t)}"
41
+ cp rel(s), rel(t)
42
+ end
43
+ if template
44
+ test = file.sub /\.tml$/, '.rb'
45
+ test = conf['test_file_prefix'] + test \
46
+ if conf['test_file_prefix']
47
+ test = File.expand_path test, tests
48
+ hash = {
49
+ file: rel(t, base),
50
+ }
51
+ code = template % hash
52
+ if ! File.exists?(test) or code != File.read(test)
53
+ action = File.exists?(test) ? 'Updating' : 'Creating'
54
+ puts "#{action} test file '#{rel test}'"
55
+ File.write test, code
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ def rel path, base='.'
62
+ base = Pathname.new(File.absolute_path(base))
63
+ Pathname.new(path).relative_path_from(base).to_s
64
+ end
65
+ end
@@ -0,0 +1,22 @@
1
+ require 'testml/runtime'
2
+
3
+ module TestML::Util
4
+ def list(value)
5
+ TestML::List.new(value)
6
+ end
7
+ def str(value)
8
+ TestML::Str.new(value)
9
+ end
10
+ def num(value)
11
+ TestML::Num.new(value)
12
+ end
13
+ def bool(value)
14
+ TestML::Bool.new(value)
15
+ end
16
+ def none(value)
17
+ TestML::None.new(value)
18
+ end
19
+ def native(value)
20
+ TestML::Native.new(value)
21
+ end
22
+ end
@@ -0,0 +1,87 @@
1
+ --- !!perl/hash:TestML::Function
2
+ namespace:
3
+ TestML: !!perl/hash:TestML::Str
4
+ value: '0.1.0'
5
+
6
+ statements:
7
+ - !!perl/hash:TestML::Assignment
8
+ name: Plan
9
+ expr: !!perl/hash:TestML::Num
10
+ value: 3
11
+ - !!perl/hash:TestML::Statement
12
+ expr: !!perl/hash:TestML::Expression
13
+ calls:
14
+ - !!perl/hash:TestML::Point
15
+ name: what
16
+ - !!perl/hash:TestML::Call
17
+ name: combine
18
+ args:
19
+ - !!perl/hash:TestML::Point
20
+ name: who
21
+ assert: !!perl/hash:TestML::Assertion
22
+ name: EQ
23
+ expr: !!perl/hash:TestML::Point
24
+ name: greeting
25
+ points:
26
+ - what
27
+ - who
28
+ - greeting
29
+ - !!perl/hash:TestML::Statement
30
+ expr: !!perl/hash:TestML::Expression
31
+ calls:
32
+ - !!perl/hash:TestML::Point
33
+ name: what
34
+ - !!perl/hash:TestML::Call
35
+ name: combine
36
+ args:
37
+ - !!perl/hash:TestML::Str
38
+ value: and
39
+ - !!perl/hash:TestML::Point
40
+ name: else
41
+ assert: !!perl/hash:TestML::Assertion
42
+ name: EQ
43
+ expr: !!perl/hash:TestML::Point
44
+ name: greeting
45
+ points:
46
+ - what
47
+ - else
48
+ - greeting
49
+ - !!perl/hash:TestML::Statement
50
+ expr: !!perl/hash:TestML::Expression
51
+ calls:
52
+ - !!perl/hash:TestML::Point
53
+ name: what
54
+ - !!perl/hash:TestML::Call
55
+ name: combine
56
+ args:
57
+ - !!perl/hash:TestML::Str
58
+ value: and
59
+ - !!perl/hash:TestML::Expression
60
+ calls:
61
+ - !!perl/hash:TestML::Point
62
+ name: else
63
+ - !!perl/hash:TestML::Call
64
+ name: uppercase
65
+ assert: !!perl/hash:TestML::Assertion
66
+ name: EQ
67
+ expr: !!perl/hash:TestML::Point
68
+ name: upper_greeting
69
+ points:
70
+ - what
71
+ - else
72
+ - upper_greeting
73
+
74
+ data:
75
+ - !!perl/hash:TestML::Block
76
+ label: Dear John
77
+ points:
78
+ what: Dear
79
+ who: John
80
+ greeting: Dear John
81
+ - !!perl/hash:TestML::Block
82
+ label: Greetings and Salutations
83
+ points:
84
+ what: Greetings
85
+ else: Salutations
86
+ greeting: Greetings and Salutations
87
+ upper_greeting: Greetings and SALUTATIONS
@@ -0,0 +1,83 @@
1
+ --- !!perl/hash:TestML::Function
2
+ namespace:
3
+ TestML: !!perl/hash:TestML::Str
4
+ value: 0.1.0
5
+ statements:
6
+ - !!perl/hash:TestML::Assignment
7
+ name: Title
8
+ expr: !!perl/hash:TestML::Str
9
+ value: A Basic TestML File
10
+ - !!perl/hash:TestML::Assignment
11
+ name: Plan
12
+ expr: !!perl/hash:TestML::Num
13
+ value: 4
14
+ - !!perl/hash:TestML::Statement
15
+ assert: !!perl/hash:TestML::Assertion
16
+ name: EQ
17
+ expr: !!perl/hash:TestML::Point
18
+ name: upper
19
+ expr: !!perl/hash:TestML::Expression
20
+ calls:
21
+ - !!perl/hash:TestML::Point
22
+ name: text
23
+ - !!perl/hash:TestML::Call
24
+ name: uppercase
25
+ points:
26
+ - text
27
+ - upper
28
+ - !!perl/hash:TestML::Statement
29
+ assert: !!perl/hash:TestML::Assertion
30
+ expr: !!perl/hash:TestML::Point
31
+ name: lower
32
+ name: EQ
33
+ expr: !!perl/hash:TestML::Expression
34
+ calls:
35
+ - !!perl/hash:TestML::Point
36
+ name: text
37
+ - !!perl/hash:TestML::Call
38
+ name: lowercase
39
+ points:
40
+ - text
41
+ - lower
42
+ - !!perl/hash:TestML::Statement
43
+ assert: !!perl/hash:TestML::Assertion
44
+ expr: !!perl/hash:TestML::Expression
45
+ calls:
46
+ - !!perl/hash:TestML::Point
47
+ name: upper
48
+ - !!perl/hash:TestML::Call
49
+ name: lowercase
50
+ - !!perl/hash:TestML::Call
51
+ name: uppercase
52
+ name: EQ
53
+ expr: !!perl/hash:TestML::Expression
54
+ calls:
55
+ - !!perl/hash:TestML::Point
56
+ name: lower
57
+ - !!perl/hash:TestML::Call
58
+ name: uppercase
59
+ points:
60
+ - lower
61
+ - upper
62
+ data:
63
+ - !!perl/hash:TestML::Block
64
+ label: Test One
65
+ points:
66
+ text: I like Pie.
67
+ upper: I LIKE PIE.
68
+ lower: i like pie.
69
+ - !!perl/hash:TestML::Block
70
+ label: Test Two
71
+ points:
72
+ text: 'Say it,
73
+
74
+ Don''t spray it.
75
+
76
+
77
+
78
+ '
79
+ lower: 'say it,
80
+
81
+ don''t spray it.
82
+
83
+ '
@@ -0,0 +1,36 @@
1
+ --- !!perl/hash:TestML::Function
2
+ namespace:
3
+ TestML: !!perl/hash:TestML::Str
4
+ value: '0.1.0'
5
+
6
+ statements:
7
+ - !!perl/hash:TestML::Assignment
8
+ name: Title
9
+ expr: !!perl/hash:TestML::Str
10
+ value: TestML with no data section
11
+ - !!perl/hash:TestML::Assignment
12
+ name: Plan
13
+ expr: !!perl/hash:TestML::Num
14
+ value: 2
15
+ - !!perl/hash:TestML::Assignment
16
+ name: Label
17
+ expr: !!perl/hash:TestML::Str
18
+ value: Test $TestNumber
19
+ - !!perl/hash:TestML::Statement
20
+ expr: !!perl/hash:TestML::Str
21
+ value: foo
22
+ assert: !!perl/hash:TestML::Assertion
23
+ name: EQ
24
+ expr: !!perl/hash:TestML::Str
25
+ value: foo
26
+ - !!perl/hash:TestML::Statement
27
+ expr: !!perl/hash:TestML::Expression
28
+ calls:
29
+ - !!perl/hash:TestML::Str
30
+ value: bar
31
+ - !!perl/hash:TestML::Call
32
+ name: Str
33
+ assert: !!perl/hash:TestML::Assertion
34
+ name: EQ
35
+ expr: !!perl/hash:TestML::Str
36
+ value: bar
@@ -0,0 +1,59 @@
1
+ --- !!perl/hash:TestML::Function
2
+ namespace:
3
+ TestML: !!perl/hash:TestML::Str
4
+ value: 0.1.0
5
+
6
+ statements:
7
+ - !!perl/hash:TestML::Assignment
8
+ name: Plan
9
+ expr: !!perl/hash:TestML::Num
10
+ value: 2
11
+ - !!perl/hash:TestML::Statement
12
+ expr: !!perl/hash:TestML::Expression
13
+ calls:
14
+ - !!perl/hash:TestML::Call
15
+ name: Throw
16
+ args:
17
+ - !!perl/hash:TestML::Point
18
+ name: error
19
+ - !!perl/hash:TestML::Call
20
+ name: NonExistingMethod
21
+ - !!perl/hash:TestML::Call
22
+ name: Catch
23
+ assert: !!perl/hash:TestML::Assertion
24
+ name: HAS
25
+ expr: !!perl/hash:TestML::Point
26
+ name: match
27
+ points:
28
+ - error
29
+ - match
30
+ - !!perl/hash:TestML::Assignment
31
+ name: message
32
+ expr: !!perl/hash:TestML::Str
33
+ value: blowed up
34
+ - !!perl/hash:TestML::Statement
35
+ expr: !!perl/hash:TestML::Expression
36
+ calls:
37
+ - !!perl/hash:TestML::Call
38
+ name: Throw
39
+ args:
40
+ - !!perl/hash:TestML::Call
41
+ name: message
42
+ - !!perl/hash:TestML::Call
43
+ name: Catch
44
+ assert: !!perl/hash:TestML::Assertion
45
+ name: EQ
46
+ expr: !!perl/hash:TestML::Call
47
+ name: message
48
+
49
+ data:
50
+ - !!perl/hash:TestML::Block
51
+ label: Error message from data
52
+ points:
53
+ error: 'O NOES!
54
+
55
+
56
+ Something went wrong
57
+
58
+ '
59
+ match: Something