testml-lite 0.0.1

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.
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ GemSpec = Gem::Specification.new do |gem|
4
+ gem.name = 'testml-lite'
5
+ gem.version = '0.0.1'
6
+ gem.license = 'MIT'
7
+ gem.required_ruby_version = '>= 1.9.1'
8
+
9
+ gem.authors << 'Ingy döt Net'
10
+ gem.email = 'ingy@ingy.net'
11
+ gem.summary = 'Acmeist Unit Test Framework'
12
+ gem.description = <<-'.'
13
+ TestML is an Acmeist testing framework. TestML::Lite is smaller bootstrap
14
+ version of TestML.
15
+ .
16
+ gem.homepage = 'http://testml.org'
17
+
18
+ gem.files = `git ls-files`.lines.map{|l|l.chomp}
19
+ end
@@ -0,0 +1,3 @@
1
+ - version: 0.0.1
2
+ date: Tue Dec 18 19:54:09 PST 2012
3
+ changes: First release
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ (The MIT License)
2
+
3
+ Copyright © 2012 Ingy döt Net
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the ‘Software’), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9
+ of the Software, and to permit persons to whom the Software is furnished to do
10
+ so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,12 @@
1
+ = testml-lite - Lite Version of TestML for Ruby
2
+
3
+ TestML is an Acmeist Unit Test language/framework. TestML::Lite is a lighter,
4
+ bootstrapping implementation of that.
5
+
6
+ = Synopsis
7
+
8
+ require 'testml/lite'
9
+
10
+ = Copyright
11
+
12
+ Copyright (c) 2012 Ingy döt Net. See LICENSE for further details.
@@ -0,0 +1,64 @@
1
+ # Load Gem constants from the gemspec
2
+ GemSpecFile = '.gemspec'
3
+ load GemSpecFile
4
+ GemName = GemSpec.name
5
+ GemVersion = GemSpec.version
6
+ GemDir = "#{GemName}-#{GemVersion}"
7
+ GemFile = "#{GemDir}.gem"
8
+ DevNull = '2>/dev/null'
9
+
10
+ # Require the Rake libraries
11
+ require 'rake'
12
+ require 'rake/testtask'
13
+ require 'rake/clean'
14
+
15
+ task :default => 'help'
16
+
17
+ CLEAN.include GemDir, GemFile, 'data.tar.gz', 'metadata.gz'
18
+
19
+ desc 'Run the tests'
20
+ task :test do
21
+ Rake::TestTask.new do |t|
22
+ t.verbose = true
23
+ t.test_files = FileList['test/*.rb']
24
+ end
25
+ end
26
+
27
+ desc 'Build the gem'
28
+ task :build => [:clean, :test] do
29
+ sh "gem build #{GemSpecFile}"
30
+ end
31
+
32
+ desc 'Install the gem'
33
+ task :install => [:build] do
34
+ sh "gem install #{GemFile}"
35
+ end
36
+
37
+ desc 'Build, unpack and inspect the gem'
38
+ task :distdir => [:build] do
39
+ sh "tar xf #{GemFile} #{DevNull}"
40
+ Dir.mkdir GemDir
41
+ Dir.chdir GemDir
42
+ sh "tar xzf ../data.tar.gz #{DevNull}"
43
+ puts "\n>>> Entering sub-shell for #{GemDir}..."
44
+ system ENV['SHELL']
45
+ end
46
+
47
+ desc 'Build and push the gem'
48
+ task :release => [:build] do
49
+ sh "gem push #{GemFile}"
50
+ end
51
+
52
+ desc 'Print a description of the gem'
53
+ task :desc do
54
+ puts "Gem: '#{GemName}' (version #{GemVersion})"
55
+ puts
56
+ puts GemSpec.description.gsub /^/, ' '
57
+ end
58
+
59
+ desc 'List the Rakefile tasks'
60
+ task :help do
61
+ puts 'The following rake tasks are available:'
62
+ puts
63
+ puts `rake -T`.gsub /^/, ' '
64
+ end
@@ -0,0 +1,218 @@
1
+ # Make sure tests have access to the application libs and the testing libs.
2
+ $:.unshift Dir.getwd + '/lib'
3
+ $:.unshift Dir.getwd + '/test/lib'
4
+
5
+ require 'test/unit'
6
+
7
+ module TestML
8
+ def self.run &runner
9
+ name = _get_test_name
10
+ $testml_runners[name] = runner
11
+ TestML::Lite::TestCases.send(:define_method, name) do
12
+ _run_runner name
13
+ end
14
+ end
15
+
16
+ def self.data data
17
+ $testml_data[_get_test_name] = data
18
+ end
19
+
20
+ def self.require_or_skip module_
21
+ require module_
22
+ rescue exit
23
+ end
24
+ end
25
+
26
+ $testml_runners ||= {}
27
+ $testml_data ||= {}
28
+
29
+ class TestML::Lite < Test::Unit::TestCase
30
+ def data input
31
+ unless input.match /\n/
32
+ File.open(input, 'r') {|f| input = f.read}
33
+ end
34
+ @testml = _parse_tml input
35
+ end
36
+
37
+ def label text
38
+ @label = text
39
+ end
40
+
41
+ def eval expr, callback=nil
42
+ _assert_testml
43
+ expr = _parse_expr expr if expr.kind_of? String
44
+ callback ||= method 'run_test'
45
+ _get_blocks(expr).each do |block|
46
+ $error = nil
47
+ callback.call(block, expr)
48
+ raise $error if $error
49
+ end
50
+ end
51
+
52
+ def run_test block, expr
53
+ expr = _parse_expr expr if expr.kind_of? String
54
+ block = _get_blocks(expr, [block]).first or return
55
+ _evaluate expr, block
56
+ end
57
+
58
+ def assert_equal got, want, block
59
+ label = block.kind_of?(String) ? block : block[:title]
60
+ if got != want
61
+ on_fail if respond_to? 'on_fail'
62
+ File.open('/tmp/got', 'w') {|f| f.write got}
63
+ File.open('/tmp/want', 'w') {|f| f.write want}
64
+ puts `diff -u /tmp/want /tmp/got`
65
+ end
66
+ super want, got, label
67
+ end
68
+
69
+ def assert_match got, want, block
70
+ label = block.kind_of?(String) ? block : block[:title]
71
+ super want, got, label
72
+ end
73
+
74
+ def Catch any=nil
75
+ fail "Catch called, but no error occurred" unless $error
76
+ error = $error
77
+ $error = nil
78
+ return error.message
79
+ end
80
+
81
+ def _run_runner name
82
+ @test_name = name
83
+ $testml_runners[name].call(self)
84
+ end
85
+
86
+ def _assert_testml
87
+ return if defined? @testml
88
+ raise "No testml data provided" unless $testml_data[@test_name]
89
+ data $testml_data[@test_name]
90
+ end
91
+
92
+ def _evaluate expr, block
93
+ expr = ['', expr] if expr.kind_of? String
94
+ func = expr.first
95
+ args = expr[1..expr.length-1].collect do |ex|
96
+ if ex.kind_of? Array
97
+ _evaluate ex, block
98
+ elsif ex =~ /\A\*(\w+)\z/
99
+ block[:points][$1]
100
+ else
101
+ ex
102
+ end
103
+ end
104
+ # TODO @error
105
+ return if $error and func != 'Catch'
106
+ return args.first if func.empty?
107
+ args << block if func =~ /^assert_/
108
+ begin
109
+ return method(func).call(*args)
110
+ rescue => e
111
+ $error = e
112
+ end
113
+ end
114
+
115
+ def _get_blocks expr, blocks=@testml
116
+ want = expr.flatten.grep(/^\*/).collect{|ex| ex.gsub /^\*/, ''}
117
+ only = blocks.select{|block| block['ONLY']}
118
+ blocks = only unless only.empty?
119
+ final = []
120
+ blocks.each do |block|
121
+ next if block['SKIP']
122
+ ok = true
123
+ want.each do |w|
124
+ unless block[:points][w]
125
+ ok = false
126
+ break
127
+ end
128
+ end
129
+ if ok
130
+ final << block
131
+ break if block['LAST']
132
+ end
133
+ end
134
+ return final
135
+ end
136
+
137
+ def _parse_expr expr
138
+ left, op, right = [], nil, nil
139
+ side = left
140
+ while expr.length != 0
141
+ t = _get_token expr
142
+ if t =~ /^(==|~~)$/
143
+ op = t == '==' ? 'assert_equal' : 'assert_match'
144
+ left = side
145
+ side = right = []
146
+ else
147
+ side = [side] if side.size >= 2
148
+ side.unshift t
149
+ end
150
+ end
151
+ right = side if right
152
+ return left unless right
153
+ left = left.first if left.size == 1
154
+ right = right.first if right.size == 1
155
+ return [op, left, right]
156
+ end
157
+
158
+ def _get_token expr
159
+ if expr.sub! /^(\w+)\(([^\)]+)\)\.?/, ''
160
+ token, args = [$1], $2
161
+ token.concat(
162
+ args.split(/,\s*/).map {|t| t.sub /^(['"])(.*)\1$/, '\2'}
163
+ )
164
+ elsif expr.sub! /^\s*(==|~~)\s*/, ''
165
+ token = $1
166
+ elsif expr.sub! /^([\*\w]+)\.?/, ''
167
+ token = $1
168
+ end
169
+ return token
170
+ end
171
+
172
+ def _parse_tml string
173
+ string.gsub! /^#.*\n/, ''
174
+ string.gsub! /^\\/, ''
175
+ string.gsub! /^\s*\n/, ''
176
+ blocks = string.split /(^===.*?(?=^===|\z))/m
177
+ blocks.reject!{|b| b.empty?}
178
+ blocks.each do |block|
179
+ block.gsub! /\n+\z/, "\n"
180
+ end
181
+
182
+ array = []
183
+ blocks.each do |string_block|
184
+ block = {}
185
+ string_block.gsub! /^===\ +(.*?)\ *\n/, '' \
186
+ or fail "No block title! #{string_block}"
187
+ block[:title] = $1
188
+ while !string_block.empty? do
189
+ if string_block.gsub! /\A---\ +(\w+):\ +(.*)\n/, '' or
190
+ string_block.gsub! /\A---\ +(\w+)\n(.*?)(?=^---|\z)/m, ''
191
+ key, value = $1, $2
192
+ else
193
+ raise "Failed to parse TestML string:\n#{string_block}"
194
+ end
195
+ block[:points] ||= {}
196
+ block[:points][key] = value
197
+
198
+ if key =~ /^(ONLY|SKIP|LAST)$/
199
+ block[key] = true
200
+ end
201
+ end
202
+ array << block
203
+ end
204
+ return array
205
+ end
206
+ end
207
+
208
+ # Find the first call stack entry that looks like: .../test/xxx-yyy.rb
209
+ # and return 'test_xxx_yyy' as the test name.
210
+ def _get_test_name
211
+ name = caller.map { |s|
212
+ s.split(':').first
213
+ }.grep(/(^|\/)test\/[-\w]+\.rb$/).first or fail
214
+ name.gsub!(/^(?:.*\/)?test\/([-\w+]+)\.rb$/, '\1').gsub(/[^\w]+/, '_')
215
+ return "test_#{name}"
216
+ end
217
+
218
+ module TestML::Lite::TestCases;end
@@ -0,0 +1,15 @@
1
+ require './lib/testml/lite'
2
+
3
+ class TestTestMLLite < TestML::Lite
4
+ include TestML::Lite::TestCases
5
+
6
+ def json_load json
7
+ require 'json'
8
+ JSON.load json
9
+ end
10
+
11
+ def yaml_dump object
12
+ require 'yaml'
13
+ YAML.dump(object).sub(/\A---\n/, '')
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ require './test/lib/test_testml_lite'
2
+
3
+ TestML.require_or_skip 'json'
4
+ TestML.require_or_skip 'yaml'
5
+
6
+ TestML.run do |t|
7
+ t.eval '*json.json_load.yaml_dump == *yaml'
8
+ end
9
+
10
+ TestML.data <<'...'
11
+ === Array
12
+ --- json: [1,2,3]
13
+ --- yaml
14
+ - 1
15
+ - 2
16
+ - 3
17
+ ...
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: testml-lite
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ingy döt Net
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-20 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: ! 'TestML is an Acmeist testing framework. TestML::Lite is smaller bootstrap
15
+
16
+ version of TestML.
17
+
18
+ '
19
+ email: ingy@ingy.net
20
+ executables: []
21
+ extensions: []
22
+ extra_rdoc_files: []
23
+ files:
24
+ - .gemspec
25
+ - CHANGELOG.yaml
26
+ - Gemfile
27
+ - LICENSE
28
+ - README.rdoc
29
+ - Rakefile
30
+ - lib/testml/lite.rb
31
+ - test/lib/test_testml_lite.rb
32
+ - test/test1.rb
33
+ homepage: http://testml.org
34
+ licenses:
35
+ - MIT
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 1.9.1
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ requirements: []
53
+ rubyforge_project:
54
+ rubygems_version: 1.8.23
55
+ signing_key:
56
+ specification_version: 3
57
+ summary: Acmeist Unit Test Framework
58
+ test_files: []