tunit 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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +113 -0
- data/Rakefile +9 -0
- data/example_spec.rb +35 -0
- data/example_test.rb +23 -0
- data/lib/tunit.rb +83 -0
- data/lib/tunit/assertion_errors.rb +43 -0
- data/lib/tunit/assertions.rb +68 -0
- data/lib/tunit/autorun.rb +8 -0
- data/lib/tunit/compound_reporter.rb +33 -0
- data/lib/tunit/hooks.rb +11 -0
- data/lib/tunit/progress_reporter.rb +11 -0
- data/lib/tunit/reporter.rb +39 -0
- data/lib/tunit/runnable.rb +51 -0
- data/lib/tunit/spec.rb +77 -0
- data/lib/tunit/summary_reporter.rb +50 -0
- data/lib/tunit/test.rb +104 -0
- data/lib/tunit/version.rb +3 -0
- data/test/rtest_test.rb +19 -0
- data/test/tunit/assertion_errors_test.rb +95 -0
- data/test/tunit/assertions_test.rb +68 -0
- data/test/tunit/progress_reporter_test.rb +45 -0
- data/test/tunit/reporter_test.rb +66 -0
- data/test/tunit/runnable_test.rb +69 -0
- data/test/tunit/spec_test.rb +57 -0
- data/test/tunit/summary_reporter_test.rb +116 -0
- data/test/tunit/test_case.rb +72 -0
- data/test/tunit/test_test.rb +181 -0
- data/tunit.gemspec +24 -0
- metadata +127 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5769b36f6ff1b870f97abe003b76ec180c387e17
|
4
|
+
data.tar.gz: 6c35816f53a6e5e5b3e1f310482338e7f263ff79
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9aeb067328c6d07e694215c0b77794a78645e4e49f71a806e9d13a0713be5b300f0585472fa893d410a6133862ba5724da8bac2f1116358bd9fff171567d37d1
|
7
|
+
data.tar.gz: 7b6754bb52f757ccfe7d1a2bb344f7fee592d2a29da47dbe896a8113b6e21a028380c050ea4fb7da851914946c6367111fcaa45abd83e964d5b11f14c93a73c4
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Teo Ljungberg
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
# Tunit
|
2
|
+
|
3
|
+
`tunit` is my take on building a testing framework, it's heavily influenced by
|
4
|
+
[minitest](https://github.com/seattlerb/minitest).
|
5
|
+
|
6
|
+
|
7
|
+
_NOTE_ This is very unstable and is just a playground for my ideas.
|
8
|
+
|
9
|
+
## Credit
|
10
|
+
Since this is heavily influenced by
|
11
|
+
[Ryan Davis](https://twitter.com/the_zenspider)' minitest there are a lot of
|
12
|
+
similarities between the two frameworks.
|
13
|
+
|
14
|
+
I wanted to see how much code and effort are needed to build a testing
|
15
|
+
framework of my own, while looking at the learnings of minitest.
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
### Unit
|
19
|
+
|
20
|
+
I personally _love_ TDD frameworks like minitest, so I tried to mimic their
|
21
|
+
behaviour and patterns as close as I possibly could. As with minitest, this is
|
22
|
+
just plain ruby.
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
class BlahTest < Tunit::Test
|
26
|
+
def setup
|
27
|
+
self.blah = Blah.new
|
28
|
+
end
|
29
|
+
attr_accessor :blah
|
30
|
+
|
31
|
+
def test_the_answer_to_everything
|
32
|
+
assert_equal 42, blah.the_ultimate_answer
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_packing_list
|
36
|
+
assert_includes blah.packing_list, "towel"
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_that_will_be_skipped
|
40
|
+
skip "test this later"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
What's important to me is that `BlahTest` is just a simple subclass, and
|
46
|
+
`test_the_answer_to_everything` is a simple method. Assertions and
|
47
|
+
lazily-loaded variables are just methods, everything is just a simple method
|
48
|
+
definition away.
|
49
|
+
|
50
|
+
I'm a strong believer in that you should only mock and stub things so you can
|
51
|
+
assert on something else. That's why a `test`-method must have assertions in
|
52
|
+
`tunit`
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
class EmptyTest < Tunit::Test
|
56
|
+
def test_im_going_to_fail
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_so_will_i
|
60
|
+
1 + 1 == 2
|
61
|
+
end
|
62
|
+
end
|
63
|
+
```
|
64
|
+
|
65
|
+
### Spec
|
66
|
+
There is also a small Spec DSL that follows along with tunit
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
require 'tunit/autorun'
|
70
|
+
|
71
|
+
Example = Class.new
|
72
|
+
|
73
|
+
describe Example do
|
74
|
+
describe 'passing tests' do
|
75
|
+
it 'even' do
|
76
|
+
assert 2.even?
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'passed once more' do
|
80
|
+
assert_includes [1, 2], 2
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe 'failing tests' do
|
85
|
+
it 'fails on empty tests' do
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'fails hard' do
|
89
|
+
refute 2.even?
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe 'skipps' do
|
94
|
+
it 'skippedy skip' do
|
95
|
+
skip
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'skips with a message' do
|
99
|
+
skip 'here!'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
```
|
104
|
+
|
105
|
+
That's it, no magic let's or subjects. Just `it` and `describe` blocks
|
106
|
+
|
107
|
+
## Contributing
|
108
|
+
|
109
|
+
1. Fork it ( http://github.com/teoljungberg/tunit/fork )
|
110
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
111
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
112
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
113
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/example_spec.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
$:<< File.join(File.dirname(__FILE__), 'lib')
|
2
|
+
require 'tunit/autorun'
|
3
|
+
|
4
|
+
Example = Class.new
|
5
|
+
|
6
|
+
describe Example do
|
7
|
+
describe 'passing tests' do
|
8
|
+
it 'even' do
|
9
|
+
assert 2.even?
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'passed once more' do
|
13
|
+
assert_includes [1, 2], 2
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'failing tests' do
|
18
|
+
it 'fails on empty tests' do
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'fails hard' do
|
22
|
+
refute 2.even?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'skipps' do
|
27
|
+
it 'skippedy skip' do
|
28
|
+
skip
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'skips with a message' do
|
32
|
+
skip 'here!'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/example_test.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
$:<< File.join(File.dirname(__FILE__), 'lib')
|
2
|
+
require 'tunit/autorun'
|
3
|
+
|
4
|
+
class ExampleTest < Tunit::Test
|
5
|
+
def test_pass
|
6
|
+
assert 2.even?
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_pass_one_more
|
10
|
+
assert_includes [1, 2], 2
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_empty
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_skip
|
17
|
+
skip
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_skip_with_message
|
21
|
+
skip 'here!'
|
22
|
+
end
|
23
|
+
end
|
data/lib/tunit.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require "tunit/compound_reporter"
|
2
|
+
require "tunit/summary_reporter"
|
3
|
+
require "tunit/progress_reporter"
|
4
|
+
require "tunit/test"
|
5
|
+
require "tunit/version"
|
6
|
+
|
7
|
+
require 'optparse'
|
8
|
+
|
9
|
+
module Tunit
|
10
|
+
meta_klass = (class << self; self; end)
|
11
|
+
meta_klass.send :attr_accessor, :reporter
|
12
|
+
|
13
|
+
# Let io be override-able in tests
|
14
|
+
meta_klass.send :attr_accessor, :io
|
15
|
+
self.io = $stdout
|
16
|
+
|
17
|
+
# Make sure that autorun is loaded after each test class has been loaded
|
18
|
+
meta_klass.send :attr_accessor, :installed_at_exit
|
19
|
+
self.installed_at_exit ||= false
|
20
|
+
|
21
|
+
def self.autorun
|
22
|
+
at_exit {
|
23
|
+
next if $! and not ($!.kind_of? SystemExit and $!.success?)
|
24
|
+
|
25
|
+
exit_code = nil
|
26
|
+
|
27
|
+
at_exit {
|
28
|
+
exit exit_code || false
|
29
|
+
}
|
30
|
+
|
31
|
+
exit_code = Tunit.run ARGV
|
32
|
+
} unless self.installed_at_exit
|
33
|
+
self.installed_at_exit = true
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.run args = []
|
37
|
+
options = process_args! args
|
38
|
+
|
39
|
+
self.reporter = CompoundReporter.new
|
40
|
+
reporter << SummaryReporter.new(options[:io], options)
|
41
|
+
reporter << ProgressReporter.new(options[:io], options)
|
42
|
+
|
43
|
+
reporter.start
|
44
|
+
dispatch! reporter, options
|
45
|
+
reporter.report
|
46
|
+
|
47
|
+
reporter.passed?
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def self.dispatch! reporter, options
|
53
|
+
Runnable.runnables.each do |runnable|
|
54
|
+
runnable.run reporter, options
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.process_args! args = []
|
59
|
+
options = { io: io }
|
60
|
+
|
61
|
+
OptionParser.new do |opts|
|
62
|
+
opts.banner = "Tunit options:"
|
63
|
+
opts.version = Tunit::VERSION
|
64
|
+
|
65
|
+
opts.on "-h", "--help", "Display this help." do
|
66
|
+
puts opts
|
67
|
+
exit
|
68
|
+
end
|
69
|
+
|
70
|
+
opts.on "-n", "--name PATTERN", "Filter run on /pattern/ or string." do |pattern|
|
71
|
+
options[:filter] = pattern
|
72
|
+
end
|
73
|
+
|
74
|
+
opts.on "-v", "--verbose", "Verbose. Show progress processing files." do
|
75
|
+
options[:verbose] = true
|
76
|
+
end
|
77
|
+
|
78
|
+
opts.parse! args
|
79
|
+
end
|
80
|
+
|
81
|
+
options
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Tunit
|
2
|
+
class Assertion < Exception
|
3
|
+
def error
|
4
|
+
self
|
5
|
+
end
|
6
|
+
|
7
|
+
def location
|
8
|
+
last_before_assertion = ""
|
9
|
+
self.backtrace.reverse_each do |line|
|
10
|
+
break if line =~ /in .(assert|refute|pass|raise)/
|
11
|
+
last_before_assertion = line
|
12
|
+
end
|
13
|
+
last_before_assertion.sub(/:in .*$/, "")
|
14
|
+
end
|
15
|
+
|
16
|
+
def result_code
|
17
|
+
result_label[0, 1]
|
18
|
+
end
|
19
|
+
|
20
|
+
def result_label
|
21
|
+
"Failure"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Empty < Assertion
|
26
|
+
# Where was the empty test
|
27
|
+
attr_accessor :location
|
28
|
+
|
29
|
+
def result_code
|
30
|
+
"_"
|
31
|
+
end
|
32
|
+
|
33
|
+
def result_label
|
34
|
+
"Empty"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Skip < Assertion
|
39
|
+
def result_label
|
40
|
+
"Skipped"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'tunit/assertion_errors'
|
2
|
+
|
3
|
+
module Tunit
|
4
|
+
module Assertions
|
5
|
+
def skip msg = nil, bt = caller
|
6
|
+
method_responsible = bt[0][/`.*'/][1..-2]
|
7
|
+
msg ||= "Skipped '#{method_responsible}'"
|
8
|
+
fail ::Tunit::Skip, msg, bt
|
9
|
+
end
|
10
|
+
|
11
|
+
def assert test, msg = nil
|
12
|
+
msg ||= "Failed assertion, no message given."
|
13
|
+
self.assertions += 1
|
14
|
+
unless test
|
15
|
+
msg = msg.call if Proc === msg
|
16
|
+
fail ::Tunit::Assertion, msg
|
17
|
+
end
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
def assert_equal exp, act, msg = nil
|
22
|
+
msg ||= "Failed assertion, no message given."
|
23
|
+
assert exp == act, msg
|
24
|
+
end
|
25
|
+
|
26
|
+
def assert_includes collection, obj, msg = nil
|
27
|
+
msg ||= "Expected #{collection.inspect} to include #{obj}"
|
28
|
+
assert_respond_to collection, :include?
|
29
|
+
assert collection.include?(obj), msg
|
30
|
+
end
|
31
|
+
|
32
|
+
def assert_respond_to obj, meth, msg = nil
|
33
|
+
msg ||= "Expected #{obj.inspect} (#{obj.class}) to respond to ##{meth}"
|
34
|
+
assert obj.respond_to?(meth), msg
|
35
|
+
end
|
36
|
+
|
37
|
+
def assert_instance_of klass, obj, msg = nil
|
38
|
+
msg ||= "Expected #{obj.inspect} to be an instance of #{klass}, not #{obj.class}"
|
39
|
+
assert obj.instance_of?(klass), msg
|
40
|
+
end
|
41
|
+
|
42
|
+
def refute test, msg = nil
|
43
|
+
msg ||= "Failed assertion, no message given."
|
44
|
+
! assert !test, msg
|
45
|
+
end
|
46
|
+
|
47
|
+
def refute_equal exp, act, msg = nil
|
48
|
+
msg ||= "Failed assertion, no message given."
|
49
|
+
refute exp == act, msg
|
50
|
+
end
|
51
|
+
|
52
|
+
def refute_includes collection, obj, msg = nil
|
53
|
+
msg ||= "Expected #{collection.inspect} to not include #{obj}"
|
54
|
+
assert_respond_to collection, :include?
|
55
|
+
refute collection.include?(obj), msg
|
56
|
+
end
|
57
|
+
|
58
|
+
def refute_respond_to obj, meth, msg = nil
|
59
|
+
msg ||= "Expected #{obj.inspect} (#{obj.class}) to not respond to #{meth}"
|
60
|
+
refute obj.respond_to?(meth), msg
|
61
|
+
end
|
62
|
+
|
63
|
+
def refute_instance_of klass, obj, msg = nil
|
64
|
+
msg ||= "Expected #{obj.inspect} not to be an instance of #{klass}"
|
65
|
+
refute obj.instance_of?(klass), msg
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|