fas_test 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.
data/README ADDED
@@ -0,0 +1,19 @@
1
+ Auto-discovers test classes in the working directory and runs the tests with
2
+ basically no boot up time and no configuration. It doesn't matter how you
3
+ structure your project, instead, simple naming conventions are used:
4
+
5
+ - All test files should be named *_tests.rb
6
+ - All test methods should be named test__*
7
+
8
+ Other things you need to know:
9
+
10
+ - All test classes should inherit FasTest::TestClass
11
+ - Your test class can define "setup" and/or "teardown" methods. They do what
12
+ it sounds like they do.
13
+
14
+ Take a look in the test folder to see an example of how the library is used.
15
+ (fas_test is used to test itself).
16
+
17
+ To actually run your tests just invoke fastest.rb from a command line. It will
18
+ automatically recursively discover all of your test classes within the working
19
+ directory and run there tests.
data/bin/fastest.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'lib/fas_test'
2
+
3
+ test_runner = FasTest::TestRunner.new
4
+ test_runner.run_tests_in_folder(".")
5
+ test_runner.print_summary
data/lib/fas_test.rb ADDED
@@ -0,0 +1,197 @@
1
+ module FasTest
2
+
3
+ # Used to discover tests and actually run them. Normally this class will be
4
+ # used by the command line client.
5
+ class TestRunner
6
+
7
+ attr_reader :test_results
8
+
9
+ def initialize(verbose = false)
10
+ @verbose = verbose
11
+ @assertion_count = 0
12
+ @test_results = {}
13
+ end
14
+
15
+ def run_tests_in_class(test_class)
16
+ test_instance = init_test_instance(test_class)
17
+ get_all_test_method_names(test_class).each do |test_method_name|
18
+ run_test(test_instance, test_method_name)
19
+ end
20
+ end
21
+
22
+ def init_test_instance(test_class)
23
+ test_instance = test_class.new
24
+ test_instance.runner = self
25
+ return test_instance
26
+ end
27
+
28
+ def increment_assert_count
29
+ @assertion_count += 1
30
+ end
31
+
32
+ def run_test(test_instance, test_method_name)
33
+ begin
34
+ status = TestStatuses::PASS
35
+ test_instance.setup
36
+ test_instance.needs_teardown = true
37
+ test_instance.send(test_method_name)
38
+ if @verbose
39
+ puts "Pass: #{test_instance.class.name}::#{test_method_name}"
40
+ end
41
+ rescue AssertionException => ex
42
+ status = TestStatuses::FAIL
43
+ try_teardown(test_instance)
44
+ puts "Fail: #{test_instance.class.name}::#{test_method_name}"
45
+ puts " -> #{ex.message}"
46
+ rescue Exception => ex
47
+ status = TestStatuses::CRASH
48
+ try_teardown(test_instance)
49
+ puts "Crash: #{test_instance.class.name}::#{test_method_name}"
50
+ puts " -> #{ex.class.name}: #{ex.message}"
51
+ pretty_print_stack_trace(ex)
52
+ rescue Object => obj
53
+ status = TestStatuses::CRASH
54
+ try_teardown(test_instance)
55
+ puts "Crash: #{test_instance.class.name}::#{test_method_name}"
56
+ puts " -> Raised non-exception: #{obj.to_s}"
57
+ ensure
58
+ try_teardown(test_instance)
59
+ record_test_result(test_instance, test_method_name, status)
60
+ end
61
+ end
62
+
63
+ def record_test_result(test_instance, test_method_name, status)
64
+ test_class = test_instance.class
65
+ key = "#{test_class.name}::#{test_method_name}"
66
+ @test_results[key] = TestResult.new(test_class, test_method_name, status)
67
+ end
68
+
69
+ def try_teardown(test_instance)
70
+ if test_instance.needs_teardown
71
+ begin
72
+ test_instance.teardown
73
+ ensure
74
+ test_instance.needs_teardown = false
75
+ end
76
+ end
77
+ end
78
+
79
+ def pretty_print_stack_trace(exception)
80
+ exception.backtrace.each { |trace| puts " #{trace}"}
81
+ end
82
+
83
+ def run_tests_in_folder(path)
84
+ load_test_files(path)
85
+ find_test_classes.each do |test_class|
86
+ run_tests_in_class(test_class)
87
+ end
88
+ end
89
+
90
+ def load_test_files(path)
91
+ Dir[File.join(path, '/**/*_tests.rb')].each { |file_name| load file_name }
92
+ end
93
+
94
+ def get_all_test_method_names(test_class)
95
+ test_class.instance_methods.find_all { |m| m.start_with?('test__') }
96
+ end
97
+
98
+ def find_test_classes
99
+ classes = []
100
+ Module.constants.each do |constant|
101
+ if constant.end_with? "Tests"
102
+ classes << eval(constant)
103
+ end
104
+ end
105
+ return classes
106
+ end
107
+
108
+ def get_constant_type(construct)
109
+ construct_class = construct.class
110
+ if construct_class == Class
111
+ return ConstantTypes::CLASS
112
+ elsif construct_class == Module
113
+ return ConstantTypes::MODULE
114
+ else
115
+ return ConstantTypes::OTHER
116
+ end
117
+ end
118
+
119
+ def class_inherits_parent?(child_class, parent_class)
120
+ child_class.ancestors.any? { |ancestor| ancestor == parent_class }
121
+ end
122
+
123
+ def print_summary
124
+ pass_count = @test_results.values.find_all { |r| r.status == TestStatuses::PASS }.length
125
+ fail_count = @test_results.length - pass_count
126
+ puts "#{pass_count} passed; #{fail_count} failed; #{@assertion_count} assertions"
127
+ end
128
+
129
+ end
130
+
131
+ # Types that a ruby constant can refer to
132
+ class ConstantTypes
133
+ CLASS = 1
134
+ MODULE = 2
135
+ OTHER = 3
136
+ end
137
+
138
+ # Base class for all test suites
139
+ class TestClass
140
+
141
+ attr_writer :runner
142
+ attr_accessor :needs_teardown
143
+
144
+ def setup
145
+ end
146
+
147
+ def teardown
148
+ end
149
+
150
+ def assert_true(expression, msg = "<no msg given>")
151
+ @runner.increment_assert_count
152
+ if expression != true
153
+ raise AssertionException, "expected true but got #{expression.to_s}"
154
+ end
155
+ end
156
+
157
+ def assert_equal(a, b, msg = "<no msg given>")
158
+ @runner.increment_assert_count
159
+ if a != b
160
+ raise AssertionException, "#{msg} | expected '#{a}' but got '#{b}'"
161
+ end
162
+ end
163
+
164
+ def fail(msg)
165
+ raise AssertionException, msg
166
+ end
167
+
168
+ end
169
+
170
+ # Represents the state of a finished test
171
+ class TestResult
172
+
173
+ attr_reader :test_class
174
+ attr_reader :method_name
175
+ attr_reader :status
176
+
177
+ def initialize(test_class, method_name, status)
178
+ @test_class = test_class
179
+ @method_name = method_name
180
+ @status = status
181
+ end
182
+
183
+ end
184
+
185
+ # Exception thrown when an assertion in a test fails
186
+ class AssertionException < Exception
187
+ end
188
+
189
+ # Enum of test result states
190
+ class TestStatuses
191
+ PASS = 1
192
+ FAIL = 2
193
+ CRASH = 3
194
+ end
195
+
196
+ end
197
+
@@ -0,0 +1,71 @@
1
+ require 'stringio'
2
+ require 'lib/fas_test'
3
+
4
+ class FasTestTests < FasTest::TestClass
5
+
6
+ def setup
7
+ $stdout = StringIO.new
8
+ end
9
+
10
+ def teardown
11
+ $stdout = STDOUT
12
+ end
13
+
14
+ def test__redirect_io
15
+ $stdout = StringIO.new
16
+ puts 'hello?'
17
+ assert_equal "hello?\n", $stdout.string
18
+ end
19
+
20
+ def test__run_tests_in_class__results_are_valid
21
+ runner = FasTest::TestRunner.new
22
+ runner.run_tests_in_class(FasTestTestClassTests)
23
+
24
+ assert_equal(5, runner.test_results.length, "wrong number of tests")
25
+
26
+ assert_equal(
27
+ FasTest::TestStatuses::PASS,
28
+ runner.test_results['FasTestTests::FasTestTestClassTests::test__pass1'].status)
29
+
30
+ assert_equal(
31
+ FasTest::TestStatuses::FAIL,
32
+ runner.test_results['FasTestTests::FasTestTestClassTests::test__fail1'].status)
33
+
34
+ assert_equal(
35
+ FasTest::TestStatuses::CRASH,
36
+ runner.test_results['FasTestTests::FasTestTestClassTests::test__crash1'].status)
37
+
38
+ assert_equal(
39
+ FasTest::TestStatuses::FAIL,
40
+ runner.test_results['FasTestTests::FasTestTestClassTests::test__assert_true_with_false'].status)
41
+
42
+ assert_equal(
43
+ FasTest::TestStatuses::PASS,
44
+ runner.test_results['FasTestTests::FasTestTestClassTests::test__asert_true_with_true'].status)
45
+ end
46
+
47
+ class FasTestTestClassTests < FasTest::TestClass
48
+
49
+ def test__pass1
50
+ end
51
+
52
+ def test__fail1
53
+ fail("this is an expected fail")
54
+ end
55
+
56
+ def test__crash1
57
+ i.am.calling.come.methods.that.dont.exist.so.it.should.crash
58
+ end
59
+
60
+ def test__assert_true_with_false
61
+ assert_true(false)
62
+ end
63
+
64
+ def test__asert_true_with_true
65
+ assert_true(true)
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fas_test
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Graeme Hill
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-24 00:00:00 -08:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: "Auto-discovers test classes in the working directory and runs the tests with\n\
23
+ basically no boot up time and no configuration. It doesn't matter how you\n\
24
+ structure your project, instead, simple naming conventions are used:\n\n - All test files should be named *_tests.rb\n - All test methods should be named test__*\n\n\
25
+ Other things you need to know:\n\n - All test classes should inherit FasTest::TestClass\n - Your test class can define \"setup\" and/or \"teardown\" methods. They do what\n it sounds like they do.\n\n\
26
+ Take a look in the test folder to see an example of how the library is used.\n\
27
+ (fas_test is used to test itself).\n\n\
28
+ To actually run your tests just invoke fastest.rb from a command line. It will\n\
29
+ automatically recursively discover all of your test classes within the working\n\
30
+ directory and run there tests. "
31
+ email: graemekh@gmail.com
32
+ executables: []
33
+
34
+ extensions: []
35
+
36
+ extra_rdoc_files:
37
+ - README
38
+ files:
39
+ - README
40
+ - bin/fastest.rb
41
+ - lib/fas_test.rb
42
+ - test/fas_test_tests.rb
43
+ has_rdoc: true
44
+ homepage: http://graemehill.ca
45
+ licenses: []
46
+
47
+ post_install_message:
48
+ rdoc_options: []
49
+
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ hash: 3
67
+ segments:
68
+ - 0
69
+ version: "0"
70
+ requirements: []
71
+
72
+ rubyforge_project:
73
+ rubygems_version: 1.5.2
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: A simple automated testing framework designed to be fast and easy to use.
77
+ test_files:
78
+ - test/fas_test_tests.rb