any-spec 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +177 -0
- data/Rakefile +43 -0
- data/VERSION +1 -0
- data/bin/any-spec +6 -0
- data/lib/any-spec.rb +1 -0
- data/lib/any-spec/assertions.rb +45 -0
- data/lib/any-spec/test-case.rb +53 -0
- data/lib/any-spec/test-runner.rb +69 -0
- data/test/fixtures/example_test_specification.yml +2 -0
- data/test/fixtures/test_cases/empty.blah +0 -0
- data/test/fixtures/test_cases/error.rb +4 -0
- data/test/fixtures/test_cases/failing.rb +5 -0
- data/test/fixtures/test_cases/incorrect.blah +1 -0
- data/test/fixtures/test_cases/test1.rb +5 -0
- data/test/fixtures/test_cases/test2.rb +5 -0
- data/test/setup/test_unit_extensions.rb +21 -0
- data/test/test_helper.rb +13 -0
- data/test/unit/assertions_test.rb +103 -0
- data/test/unit/test_case_test.rb +44 -0
- data/test/unit/test_runner_test.rb +37 -0
- metadata +96 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Aaron Gough (http://thingsaaronmade.com/)
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
= AnySpec
|
2
|
+
|
3
|
+
AnySpec is a framework for writing executable language specifications for programming languages. AnySpec makes it easy to write an automated black-box test suite for a target language. AnySpec test-cases are completely language agnostic, though the assertions associated with a test-case are written in Ruby.
|
4
|
+
|
5
|
+
To maintain its independence from the language under test AnySpec expects that a test-case will run some arbitrary text file against an executable, and then the output from that executable will be assessed using the assertions defined in the test-case. This method of operation has the disadvantage that introspection into the internals of the executable is not possible, but has the advantage that the target language does not have to be advanced in its development to be targeted, unlike an in-language specification like RubySpec.
|
6
|
+
|
7
|
+
=== Example Tests
|
8
|
+
|
9
|
+
Test cases written using AnySpec combine the program code under test and the test assertions into a single file. The program code is defined first, then a separator is inserted, then the assertions are defined:
|
10
|
+
|
11
|
+
(define test 1)
|
12
|
+
(display test)
|
13
|
+
|
14
|
+
----
|
15
|
+
|
16
|
+
assert_output "1"
|
17
|
+
assert_execution_success
|
18
|
+
|
19
|
+
Writing a 'dirty' test is also easy:
|
20
|
+
|
21
|
+
(define 1_invalid_identifier 1)
|
22
|
+
|
23
|
+
----
|
24
|
+
|
25
|
+
assert_execution_failure
|
26
|
+
|
27
|
+
Having a test-case that does not contain 'assert_execution_failure' implies that the test should execute successfully. Therefore:
|
28
|
+
|
29
|
+
puts 1
|
30
|
+
|
31
|
+
----
|
32
|
+
|
33
|
+
assert_output "1"
|
34
|
+
|
35
|
+
Is equivalent to:
|
36
|
+
|
37
|
+
puts 1
|
38
|
+
|
39
|
+
----
|
40
|
+
|
41
|
+
assert_output "1"
|
42
|
+
assert_execution_success
|
43
|
+
|
44
|
+
=== Installation
|
45
|
+
|
46
|
+
For convenience AnySpec is packaged as a RubyGem. If you already have Ruby and RubyGems installed, then installing AnySpec is as easy as entering this at your command line:
|
47
|
+
|
48
|
+
> gem install any-spec
|
49
|
+
|
50
|
+
Mac OS X and most flavours of Linux come with Ruby and RubyGems preinstalled. If you do not have them installed please check the {installation instructions on the Ruby website}[http://www.ruby-lang.org/en/downloads/]
|
51
|
+
|
52
|
+
=== Usage
|
53
|
+
|
54
|
+
AnySpec expects that you define a small specification file in YAML format telling it where your test-cases are and what their file-extension is, for instance:
|
55
|
+
|
56
|
+
# in file: r5rs-spec.yaml
|
57
|
+
specification_root: test_cases
|
58
|
+
specification_extension: .scm
|
59
|
+
|
60
|
+
AnySpec will look for test cases recursively inside the 'specification_root' folder, so with this specification file, the directory structure for your specification might look like this:
|
61
|
+
|
62
|
+
r5rs-spec
|
63
|
+
|
|
64
|
+
|- r5rs-spec.yaml
|
65
|
+
|- test_cases
|
66
|
+
|
|
67
|
+
|- 01-output-tests
|
68
|
+
| |
|
69
|
+
| |- 01-display-test.scm
|
70
|
+
| |- 02-stderr-test.scm
|
71
|
+
|
|
72
|
+
|- 02-variable-tests
|
73
|
+
|
|
74
|
+
|- 01-define-test.scm
|
75
|
+
|- 02-set-test.scm
|
76
|
+
|
77
|
+
Any files that have a different extension to the one specified using 'specification_extension' will be ignored. Any matching files will be executed in directory/file order, which allows you to specify which order the test cases should be run in.
|
78
|
+
|
79
|
+
Once you have your specification file and test-cases in order you can run them using the AnySpec command line interface:
|
80
|
+
|
81
|
+
> any-spec executable_to_target path_to_specification_file
|
82
|
+
|
83
|
+
This makes it very easy to run a specification against multiple runtimes for a given language, and can also help a lot when trying to initially bootstrap a language.
|
84
|
+
|
85
|
+
=== API
|
86
|
+
|
87
|
+
AnySpec currently defines a small set of assertions:
|
88
|
+
|
89
|
+
# Make the test-case always fail, good as a reminder that you haven't yet fully
|
90
|
+
# implemented a particular test-case
|
91
|
+
flunk
|
92
|
+
|
93
|
+
# Assert that the test-case runs and exits successfully (returns exit status 0)
|
94
|
+
assert_execution_success
|
95
|
+
|
96
|
+
# Assert that the test-case does not execute cleanly (returns an exit status other than 0)
|
97
|
+
assert_execution_failure
|
98
|
+
|
99
|
+
# Assert that the test-case outputs a given string to either STDOUT or STDERR
|
100
|
+
assert_output "YOUR STRING HERE"
|
101
|
+
|
102
|
+
AnySpec assertions are all written in Ruby and executed in the context of the test-case. You can build your own custom assertions using the following generic assertions:
|
103
|
+
|
104
|
+
# Assert that 'expression' evaluates to true
|
105
|
+
assert expression
|
106
|
+
|
107
|
+
# Assert that the result of a block of custom code is true
|
108
|
+
assert_block("Your custom failure message here") do
|
109
|
+
...
|
110
|
+
your_custom_code_here
|
111
|
+
...
|
112
|
+
return result # true or false
|
113
|
+
end
|
114
|
+
|
115
|
+
For example:
|
116
|
+
|
117
|
+
assert 1 == 2 # "false is not true"
|
118
|
+
assert nil # "nil is not true"
|
119
|
+
assert 1 == 1 # passes
|
120
|
+
|
121
|
+
assert_block("There is something wrong with the universe!") do
|
122
|
+
true == true
|
123
|
+
end
|
124
|
+
|
125
|
+
If necessary you can also write completely custom Ruby code that has access to the data from the test-case. Accessor methods provided by the test case are:
|
126
|
+
|
127
|
+
# The result of the last assertion, if it is 'false' no further assertions should be run
|
128
|
+
@test_case.last_assertion_result
|
129
|
+
|
130
|
+
# The captured output from the test-case (AnySpec captures output to STDOUT and STDERR)
|
131
|
+
@test_case.test_output
|
132
|
+
|
133
|
+
# The number of assertions that have already been run against this test-case.
|
134
|
+
# If you write custom assertions (not using 'assert' or 'assert_block') then
|
135
|
+
# you will need to increment this counter manually for each assertion you run
|
136
|
+
@test_case.assertions
|
137
|
+
|
138
|
+
# The message that will be output if the assertions fail, this is set automatically
|
139
|
+
# by the built-in assertions, but you will need to set it manually if you write your own
|
140
|
+
@test_case.message
|
141
|
+
|
142
|
+
An example of a custom assertion:
|
143
|
+
|
144
|
+
module AnySpec
|
145
|
+
class Assertions
|
146
|
+
|
147
|
+
# Lets create a custom assertion
|
148
|
+
def always_fail
|
149
|
+
# Avoid running this assertion if a previous assertion has already failed
|
150
|
+
# all the built-in assertions do this, and all custom ones should too
|
151
|
+
return if(@test_case.last_assertion_result == false)
|
152
|
+
|
153
|
+
# Set the assertion result to false because we're always failing
|
154
|
+
@test_case.last_assertion_result = false
|
155
|
+
|
156
|
+
# Set the failure message, this will be displayed to whoever is running the test suite
|
157
|
+
@test_case.message = "This assertion always fails, the output of the test-case was:\n"
|
158
|
+
|
159
|
+
# Add the test-case output to the failure message so the user can see it
|
160
|
+
@test_case.message += @test_case.test_output + "\n\n"
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
=== Contributing and Feedback
|
168
|
+
|
169
|
+
If you have an issue with AnySpec or would like to see specific functionality added to it please email me at: aaron@aarongough.com
|
170
|
+
|
171
|
+
If you would like to provide a patch please fork AnySpec, write your patches and then send me a pull request. Make sure you write tests for your new functionality so I don't accidentally break it in the future. Please do not touch VERSION or Rakefile.
|
172
|
+
|
173
|
+
=== Author & Credits
|
174
|
+
|
175
|
+
Author:: {Aaron Gough}[mailto:aaron@aarongough.com]
|
176
|
+
|
177
|
+
Copyright (c) 2010 {Aaron Gough}[http://thingsaaronmade.com/] ({thingsaaronmade.com}[http://thingsaaronmade.com/]), released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'jeweler'
|
10
|
+
Jeweler::Tasks.new do |gemspec|
|
11
|
+
gemspec.name = "any-spec"
|
12
|
+
gemspec.summary = "A framework for writing executable language specifications"
|
13
|
+
gemspec.description = "AnySpec is a framework for writing executable language specifications and automated black-box functional tests for programming languages."
|
14
|
+
gemspec.email = "aaron@aarongough.com"
|
15
|
+
gemspec.homepage = "http://github.com/aarongough/any-spec"
|
16
|
+
gemspec.authors = ["Aaron Gough"]
|
17
|
+
gemspec.rdoc_options << '--line-numbers' << '--inline-source'
|
18
|
+
gemspec.extra_rdoc_files = ['README.rdoc', 'MIT-LICENSE']
|
19
|
+
gemspec.executables << "any-spec"
|
20
|
+
end
|
21
|
+
rescue LoadError
|
22
|
+
puts "Jeweler not available. Install it with: gem install jeweler"
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
desc 'Test AnySpec.'
|
27
|
+
Rake::TestTask.new(:test) do |t|
|
28
|
+
t.libs << 'lib/*.rb'
|
29
|
+
t.libs << 'test'
|
30
|
+
t.pattern = 'test/**/*_test.rb'
|
31
|
+
t.verbose = true
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
desc 'Generate documentation for AnySpec.'
|
36
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
37
|
+
rdoc.rdoc_dir = 'rdoc'
|
38
|
+
rdoc.title = 'AnySpec'
|
39
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
40
|
+
rdoc.rdoc_files.include('README.rdoc')
|
41
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
42
|
+
rdoc.rdoc_files.include('app/**/*.rb')
|
43
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
data/bin/any-spec
ADDED
data/lib/any-spec.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Dir[File.join(File.dirname(__FILE__), 'any-spec', '**', '*.rb')].each {|file| require File.expand_path(file) }
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module AnySpec
|
2
|
+
class Assertions
|
3
|
+
|
4
|
+
def initialize(test_case_instance)
|
5
|
+
@test_case = test_case_instance
|
6
|
+
end
|
7
|
+
|
8
|
+
def flunk
|
9
|
+
message = "Flunked."
|
10
|
+
assert_block(message) { false }
|
11
|
+
end
|
12
|
+
|
13
|
+
def assert( expression )
|
14
|
+
message = "#{expression.inspect} is not true"
|
15
|
+
assert_block(message) { expression == true }
|
16
|
+
end
|
17
|
+
|
18
|
+
def assert_output(expected, output = @test_case.test_output)
|
19
|
+
message = "Expected output to be:\n<#{expected.inspect}> but was:\n<#{output.inspect}>"
|
20
|
+
assert_block(message) { output == expected }
|
21
|
+
end
|
22
|
+
|
23
|
+
def assert_execution_success
|
24
|
+
message = "Execution of test case failed when it was expected to succeed:\n"
|
25
|
+
message += @test_case.test_output
|
26
|
+
assert_block(message) { @test_case.exit_status == 0 }
|
27
|
+
end
|
28
|
+
|
29
|
+
def assert_execution_failure
|
30
|
+
message = "Execution of test case succeeded when it was expected to fail:\n"
|
31
|
+
message += @test_case.test_output
|
32
|
+
assert_block(message) { @test_case.exit_status != 0 }
|
33
|
+
end
|
34
|
+
|
35
|
+
def assert_block(message = "assert_block failed")
|
36
|
+
return if(@test_case.last_assertion_result == false)
|
37
|
+
@test_case.assertions += 1
|
38
|
+
unless( yield )
|
39
|
+
@test_case.last_assertion_result = false
|
40
|
+
@test_case.message = message
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module AnySpec
|
2
|
+
class TestCase
|
3
|
+
|
4
|
+
attr_accessor :test_code,
|
5
|
+
:assertion_code,
|
6
|
+
:target_executable,
|
7
|
+
:path,
|
8
|
+
:last_assertion_result,
|
9
|
+
:message,
|
10
|
+
:test_output,
|
11
|
+
:exit_status,
|
12
|
+
:assertions
|
13
|
+
|
14
|
+
def initialize(path, target_executable)
|
15
|
+
raise Exception, "\n\nNo test case exists at path: #{path}" unless(File.exist?(path))
|
16
|
+
raise Exception, "\n\nTest case is empty: #{path}" if(File.size(path) == 0)
|
17
|
+
raw_test = File.open(path).read
|
18
|
+
test_parts = raw_test.split("----")
|
19
|
+
raise Exception, "\n\nTest case formatted incorrectly: #{path}" unless(test_parts.length == 2)
|
20
|
+
@test_code = test_parts[0].strip
|
21
|
+
@assertion_code = test_parts[1].strip
|
22
|
+
@path = path
|
23
|
+
@target_executable = target_executable
|
24
|
+
end
|
25
|
+
|
26
|
+
def run
|
27
|
+
temporary_filename = File.join( File.split(@path)[0], "#{Time.now.to_i}-any-spec" + File.extname(@path) )
|
28
|
+
tmp = File.open(temporary_filename, "w")
|
29
|
+
tmp.write(@test_code)
|
30
|
+
tmp.close
|
31
|
+
@test_output = `#{@target_executable} #{temporary_filename} 2>&1`
|
32
|
+
@exit_status = $?.exitstatus
|
33
|
+
@last_assertion_result = true
|
34
|
+
@message = ""
|
35
|
+
@assertions = 0
|
36
|
+
unless(@assertion_code.include?("assert_execution_success") || @assertion_code.include?("assert_execution_failure"))
|
37
|
+
@assertion_code = "\nassert_execution_success\n" + @assertion_code
|
38
|
+
end
|
39
|
+
begin
|
40
|
+
AnySpec::Assertions.new(self).instance_eval(@assertion_code, @path)
|
41
|
+
rescue Exception => e
|
42
|
+
@message = "Error in assertion code:\n"
|
43
|
+
@message += e.message
|
44
|
+
@message += "\n" + e.backtrace.join("\n")
|
45
|
+
@last_assertion_result = false
|
46
|
+
end
|
47
|
+
return @last_assertion_result
|
48
|
+
ensure
|
49
|
+
File.delete(temporary_filename)
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module AnySpec
|
2
|
+
class TestRunner
|
3
|
+
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
attr_accessor :target_executable,
|
7
|
+
:specification_root,
|
8
|
+
:specification_extension,
|
9
|
+
:test_case_paths,
|
10
|
+
:test_cases,
|
11
|
+
:report
|
12
|
+
|
13
|
+
def initialize( target_executable, test_specification_file )
|
14
|
+
# Verify that the target executable exists and is in the current PATH
|
15
|
+
@target_executable = `which #{target_executable}`.strip
|
16
|
+
raise Exception, "The target executable you specified does not exist!" if(@target_executable.empty?)
|
17
|
+
# Load the test specification file
|
18
|
+
@test_specification_file = File.expand_path(test_specification_file)
|
19
|
+
raise Exception, "The test specification file you supplied does not exist." unless(File.exist? @test_specification_file)
|
20
|
+
test_spec = YAML::load_file(@test_specification_file)
|
21
|
+
@specification_root = test_spec["specification_root"]
|
22
|
+
@specification_extension = test_spec["specification_extension"]
|
23
|
+
# Find and load test-case file paths
|
24
|
+
@test_case_paths = Dir[File.join(File.split(@test_specification_file)[0], @specification_root, '**', "*" + @specification_extension)].sort
|
25
|
+
# Instantiate the test cases
|
26
|
+
@test_cases = @test_case_paths.map do |test_case|
|
27
|
+
AnySpec::TestCase.new(test_case, @target_executable)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def run_tests(silence = false)
|
32
|
+
@report = ""
|
33
|
+
@silence = silence
|
34
|
+
message "\nLoaded suite: #{@test_specification_file}\n"
|
35
|
+
message "Targeting: #{@target_executable}\n"
|
36
|
+
message "\nStarted\n"
|
37
|
+
start_time = Time.now
|
38
|
+
assertions = 0
|
39
|
+
failed_tests = []
|
40
|
+
@test_cases.each do |test_case|
|
41
|
+
result = test_case.run
|
42
|
+
message "." if(result)
|
43
|
+
message "F" if(!result)
|
44
|
+
assertions += test_case.assertions
|
45
|
+
failed_tests << test_case if(!result)
|
46
|
+
end
|
47
|
+
message "\nFinished in #{(Time.now - start_time).to_f} seconds.\n\n"
|
48
|
+
failed_tests.each_index do |x|
|
49
|
+
test_case = failed_tests[x]
|
50
|
+
message " #{x + 1}) Failure:\n"
|
51
|
+
message "In file: " + test_case.path.gsub(File.split(@test_specification_file)[0], "") + "\n"
|
52
|
+
message test_case.message + "\n\n"
|
53
|
+
end
|
54
|
+
pass_rate = format("%.2f",((failed_tests.length.to_f) / @test_cases.length) * 100)
|
55
|
+
message "#{@test_cases.length} tests, #{assertions} assertions, #{failed_tests.count} failures, #{pass_rate}% pass rate\n\n"
|
56
|
+
return @test_cases
|
57
|
+
end
|
58
|
+
|
59
|
+
def message(string)
|
60
|
+
if(@silence)
|
61
|
+
@report << string
|
62
|
+
else
|
63
|
+
print string
|
64
|
+
$stdout.flush
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
blah
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Test::Unit
|
2
|
+
# Used to fix a minor minitest/unit incompatibility in flexmock
|
3
|
+
AssertionFailedError = Class.new(StandardError)
|
4
|
+
|
5
|
+
class TestCase
|
6
|
+
|
7
|
+
def self.test(name, &block)
|
8
|
+
test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym
|
9
|
+
defined = instance_method(test_name) rescue false
|
10
|
+
raise "#{test_name} is already defined in #{self}" if defined
|
11
|
+
if block_given?
|
12
|
+
define_method(test_name, &block)
|
13
|
+
else
|
14
|
+
define_method(test_name) do
|
15
|
+
flunk "No implementation provided for #{name}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
$test = true
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'test/unit'
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
require_files = []
|
8
|
+
require_files << File.join(File.dirname(__FILE__), '..', 'lib', 'any-spec.rb')
|
9
|
+
require_files.concat Dir[File.join(File.dirname(__FILE__), 'setup', '*.rb')]
|
10
|
+
|
11
|
+
require_files.each do |file|
|
12
|
+
require File.expand_path(file)
|
13
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class AssertionsTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
require 'ostruct'
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@test_case = OpenStruct.new
|
9
|
+
@test_case.last_assertion_result = true
|
10
|
+
@test_case.message = ""
|
11
|
+
@test_case.assertions = 0
|
12
|
+
end
|
13
|
+
|
14
|
+
test "assert_block should pass when block returns true" do
|
15
|
+
AnySpec::Assertions.new(@test_case).assert_block {true}
|
16
|
+
assert_equal true, @test_case.last_assertion_result
|
17
|
+
assert_equal "", @test_case.message
|
18
|
+
end
|
19
|
+
|
20
|
+
test "assert_block should increment assertion counter" do
|
21
|
+
AnySpec::Assertions.new(@test_case).assert_block {true}
|
22
|
+
assert_equal 1, @test_case.assertions
|
23
|
+
AnySpec::Assertions.new(@test_case).assert_block {true}
|
24
|
+
assert_equal 2, @test_case.assertions
|
25
|
+
end
|
26
|
+
|
27
|
+
test "assert_block should fail when block returns false" do
|
28
|
+
AnySpec::Assertions.new(@test_case).assert_block {false}
|
29
|
+
assert_equal false, @test_case.last_assertion_result
|
30
|
+
assert_equal "assert_block failed", @test_case.message
|
31
|
+
end
|
32
|
+
|
33
|
+
test "flunk should flunk" do
|
34
|
+
AnySpec::Assertions.new(@test_case).flunk
|
35
|
+
assert_equal false, @test_case.last_assertion_result
|
36
|
+
assert_equal "Flunked.", @test_case.message
|
37
|
+
end
|
38
|
+
|
39
|
+
test "assert should assert truthiness" do
|
40
|
+
AnySpec::Assertions.new(@test_case).assert(true)
|
41
|
+
assert_equal true, @test_case.last_assertion_result
|
42
|
+
assert_equal "", @test_case.message
|
43
|
+
end
|
44
|
+
|
45
|
+
test "assert should fail on false" do
|
46
|
+
AnySpec::Assertions.new(@test_case).assert(false)
|
47
|
+
assert_equal false, @test_case.last_assertion_result
|
48
|
+
assert_equal "false is not true", @test_case.message
|
49
|
+
end
|
50
|
+
|
51
|
+
test "assert should fail on nil" do
|
52
|
+
AnySpec::Assertions.new(@test_case).assert(nil)
|
53
|
+
assert_equal false, @test_case.last_assertion_result
|
54
|
+
assert_equal "nil is not true", @test_case.message
|
55
|
+
end
|
56
|
+
|
57
|
+
test "assert_output should pass when output matches" do
|
58
|
+
@test_case.test_output = "test"
|
59
|
+
AnySpec::Assertions.new(@test_case).assert_output("test")
|
60
|
+
assert_equal true, @test_case.last_assertion_result
|
61
|
+
assert_equal "", @test_case.message
|
62
|
+
end
|
63
|
+
|
64
|
+
test "assert_output should fail when output does not match" do
|
65
|
+
@test_case.test_output = "test2"
|
66
|
+
AnySpec::Assertions.new(@test_case).assert_output("test")
|
67
|
+
assert_equal false, @test_case.last_assertion_result
|
68
|
+
assert_equal "Expected output to be:\n<\"test\"> but was:\n<\"test2\">", @test_case.message
|
69
|
+
end
|
70
|
+
|
71
|
+
test "assert_execution_success should pass when exit_status == 0" do
|
72
|
+
@test_case.exit_status = 0
|
73
|
+
@test_case.test_output = ""
|
74
|
+
AnySpec::Assertions.new(@test_case).assert_execution_success
|
75
|
+
assert_equal true, @test_case.last_assertion_result
|
76
|
+
assert_equal '', @test_case.message
|
77
|
+
end
|
78
|
+
|
79
|
+
test "assert_execution_success should fail when exit_status != 0" do
|
80
|
+
@test_case.test_output = "test2"
|
81
|
+
@test_case.exit_status = 1
|
82
|
+
AnySpec::Assertions.new(@test_case).assert_execution_success
|
83
|
+
assert_equal false, @test_case.last_assertion_result
|
84
|
+
assert_equal "Execution of test case failed when it was expected to succeed:\ntest2", @test_case.message
|
85
|
+
end
|
86
|
+
|
87
|
+
test "assert_execution_failure should fail when exit_status == 0" do
|
88
|
+
@test_case.test_output = "test2"
|
89
|
+
@test_case.exit_status = 0
|
90
|
+
AnySpec::Assertions.new(@test_case).assert_execution_failure
|
91
|
+
assert_equal false, @test_case.last_assertion_result
|
92
|
+
assert_equal "Execution of test case succeeded when it was expected to fail:\ntest2", @test_case.message
|
93
|
+
end
|
94
|
+
|
95
|
+
test "assert_execution_failure should pass when exit_status != 0" do
|
96
|
+
@test_case.exit_status = 1
|
97
|
+
@test_case.test_output = ""
|
98
|
+
AnySpec::Assertions.new(@test_case).assert_execution_failure
|
99
|
+
assert_equal true, @test_case.last_assertion_result
|
100
|
+
assert_equal '', @test_case.message
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class TestCaseTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@test_file = File.expand_path(File.join(File.dirname(__FILE__), '..', 'fixtures', 'test_cases', 'test1.rb'))
|
7
|
+
end
|
8
|
+
|
9
|
+
test "should load test case" do
|
10
|
+
test_case = AnySpec::TestCase.new(@test_file, "ruby")
|
11
|
+
assert_equal test_case.test_code, 'print "this is a test"'
|
12
|
+
assert_equal test_case.assertion_code, 'assert_output "this is a test"'
|
13
|
+
assert_equal "ruby", test_case.target_executable
|
14
|
+
assert_equal @test_file, test_case.path
|
15
|
+
end
|
16
|
+
|
17
|
+
test "should run test case" do
|
18
|
+
test_case = AnySpec::TestCase.new(@test_file, "ruby")
|
19
|
+
result = test_case.run
|
20
|
+
assert_equal true, result
|
21
|
+
end
|
22
|
+
|
23
|
+
test "test case that is not formatted correctly should raise exception" do
|
24
|
+
assert_raises Exception do
|
25
|
+
@test_file = File.expand_path(File.join(File.dirname(__FILE__), '..', 'fixtures', 'test_cases', 'incorrect.blah'))
|
26
|
+
test_case = AnySpec::TestCase.new(@test_file, "ruby")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
test "empty test case should raise exception" do
|
31
|
+
assert_raises Exception do
|
32
|
+
@test_file = File.expand_path(File.join(File.dirname(__FILE__), '..', 'fixtures', 'test_cases', 'empty.blah'))
|
33
|
+
test_case = AnySpec::TestCase.new(@test_file, "ruby")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
test "test case that does not exist should raise exception" do
|
38
|
+
assert_raises Exception do
|
39
|
+
@test_file = File.expand_path(File.join(File.dirname(__FILE__), '..', 'fixtures', 'test_cases', 'does_not_exist.blah'))
|
40
|
+
test_case = AnySpec::TestCase.new(@test_file, "ruby")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class TestRunnerTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@spec_file = File.expand_path(File.join(File.dirname(__FILE__), '..', 'fixtures', 'example_test_specification.yml'))
|
7
|
+
@spec = YAML::load_file(@spec_file)
|
8
|
+
end
|
9
|
+
|
10
|
+
test "should create new TestRunner instance" do
|
11
|
+
test_runner = AnySpec::TestRunner.new("ruby", @spec_file)
|
12
|
+
assert_equal `which ruby`.strip, test_runner.target_executable
|
13
|
+
assert_equal @spec["specification_root"], test_runner.specification_root
|
14
|
+
assert_equal @spec["specification_extension"], test_runner.specification_extension
|
15
|
+
assert_equal 4, test_runner.test_case_paths.length
|
16
|
+
assert_equal 4, test_runner.test_cases.length
|
17
|
+
end
|
18
|
+
|
19
|
+
test "should raise error when target executable does not exist" do
|
20
|
+
assert_raises Exception do
|
21
|
+
test_runner = AnySpec::TestRunner.new("blagitz", @spec_file)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
test "should raise error when specification file does not exist" do
|
26
|
+
assert_raises Exception do
|
27
|
+
test_runner = AnySpec::TestRunner.new("ruby", "~/blah/foo/blag.bar")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
test "should run test cases" do
|
32
|
+
test_runner = AnySpec::TestRunner.new("ruby", @spec_file)
|
33
|
+
results = test_runner.run_tests(true)
|
34
|
+
assert_equal 4, results.length
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: any-spec
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 0.0.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Aaron Gough
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-10-08 00:00:00 -04:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: AnySpec is a framework for writing executable language specifications and automated black-box functional tests for programming languages.
|
22
|
+
email: aaron@aarongough.com
|
23
|
+
executables:
|
24
|
+
- any-spec
|
25
|
+
- any-spec
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files:
|
29
|
+
- MIT-LICENSE
|
30
|
+
- README.rdoc
|
31
|
+
files:
|
32
|
+
- MIT-LICENSE
|
33
|
+
- README.rdoc
|
34
|
+
- Rakefile
|
35
|
+
- VERSION
|
36
|
+
- bin/any-spec
|
37
|
+
- lib/any-spec.rb
|
38
|
+
- lib/any-spec/assertions.rb
|
39
|
+
- lib/any-spec/test-case.rb
|
40
|
+
- lib/any-spec/test-runner.rb
|
41
|
+
- test/fixtures/example_test_specification.yml
|
42
|
+
- test/fixtures/test_cases/empty.blah
|
43
|
+
- test/fixtures/test_cases/error.rb
|
44
|
+
- test/fixtures/test_cases/failing.rb
|
45
|
+
- test/fixtures/test_cases/incorrect.blah
|
46
|
+
- test/fixtures/test_cases/test1.rb
|
47
|
+
- test/fixtures/test_cases/test2.rb
|
48
|
+
- test/setup/test_unit_extensions.rb
|
49
|
+
- test/test_helper.rb
|
50
|
+
- test/unit/assertions_test.rb
|
51
|
+
- test/unit/test_case_test.rb
|
52
|
+
- test/unit/test_runner_test.rb
|
53
|
+
has_rdoc: true
|
54
|
+
homepage: http://github.com/aarongough/any-spec
|
55
|
+
licenses: []
|
56
|
+
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options:
|
59
|
+
- --charset=UTF-8
|
60
|
+
- --line-numbers
|
61
|
+
- --inline-source
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
version: "0"
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
segments:
|
78
|
+
- 0
|
79
|
+
version: "0"
|
80
|
+
requirements: []
|
81
|
+
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 1.3.7
|
84
|
+
signing_key:
|
85
|
+
specification_version: 3
|
86
|
+
summary: A framework for writing executable language specifications
|
87
|
+
test_files:
|
88
|
+
- test/fixtures/test_cases/error.rb
|
89
|
+
- test/fixtures/test_cases/failing.rb
|
90
|
+
- test/fixtures/test_cases/test1.rb
|
91
|
+
- test/fixtures/test_cases/test2.rb
|
92
|
+
- test/setup/test_unit_extensions.rb
|
93
|
+
- test/test_helper.rb
|
94
|
+
- test/unit/assertions_test.rb
|
95
|
+
- test/unit/test_case_test.rb
|
96
|
+
- test/unit/test_runner_test.rb
|