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.
- data/.gemspec +3 -1
- data/CHANGELOG.yaml +4 -1
- data/LICENSE +1 -1
- data/README.rdoc +30 -5
- data/Rakefile +10 -1
- data/ToDo +56 -0
- data/lib/rake/testml.rb +14 -0
- data/lib/testml.rb +46 -2
- data/lib/testml/bridge.rb +5 -0
- data/lib/testml/compiler.rb +106 -0
- data/lib/testml/compiler/lite.rb +194 -0
- data/lib/testml/compiler/pegex.rb +50 -0
- data/lib/testml/compiler/pegex/ast.rb +145 -0
- data/lib/testml/compiler/pegex/grammar.rb +173 -0
- data/lib/testml/library.rb +7 -0
- data/lib/testml/library/debug.rb +18 -0
- data/lib/testml/library/standard.rb +86 -0
- data/lib/testml/runtime.rb +501 -0
- data/lib/testml/runtime/unit.rb +94 -0
- data/lib/testml/setup.rb +65 -0
- data/lib/testml/util.rb +22 -0
- data/test/ast/arguments.tml +87 -0
- data/test/ast/basic.tml +83 -0
- data/test/ast/dataless.tml +36 -0
- data/test/ast/exceptions.tml +59 -0
- data/test/ast/external.tml +42 -0
- data/test/ast/function.tml +276 -0
- data/test/ast/label.tml +58 -0
- data/test/ast/markers.tml +36 -0
- data/test/ast/semicolons.tml +30 -0
- data/test/ast/truth.tml +85 -0
- data/test/ast/types.tml +163 -0
- data/test/compile-lite.rb +38 -0
- data/test/compile-testml-document.rb +59 -0
- data/test/compile.rb +57 -0
- data/test/inline-bridge.rb +30 -0
- data/test/inline.rb +28 -0
- data/test/strings.rb +24 -0
- data/test/testml.rb +38 -0
- data/test/testml.yaml +10 -0
- data/test/testml/arguments.tml +18 -0
- data/test/testml/assertions.tml +15 -0
- data/test/testml/basic.tml +37 -0
- data/test/testml/dataless.tml +9 -0
- data/test/testml/exceptions.tml +16 -0
- data/test/testml/external.tml +8 -0
- data/test/testml/external1.tml +10 -0
- data/test/testml/external2.tml +3 -0
- data/test/testml/function.tml +82 -0
- data/test/testml/label.tml +24 -0
- data/test/testml/markers.tml +19 -0
- data/test/testml/semicolons.tml +10 -0
- data/test/testml/standard.tml +50 -0
- data/test/testml/truth.tml +22 -0
- data/test/testml/types.tml +24 -0
- data/test/testml_bridge.rb +28 -0
- metadata +69 -4
- 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
|
data/lib/testml/setup.rb
ADDED
@@ -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
|
data/lib/testml/util.rb
ADDED
@@ -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
|
data/test/ast/basic.tml
ADDED
@@ -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
|