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.
@@ -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
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in tunit.gemspec
4
+ gemspec
@@ -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.
@@ -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
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ ENV["RUBYOPT"] = "-w"
6
+ t.pattern = "test/**/*_test.rb"
7
+ t.libs << "test"
8
+ end
9
+ task :default => :test
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,8 @@
1
+ require "tunit/test"
2
+ require "tunit/spec"
3
+ require "tunit/compound_reporter"
4
+ require "tunit/summary_reporter"
5
+ require "tunit/progress_reporter"
6
+ require "tunit"
7
+
8
+ Tunit.autorun