testy 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,160 @@
1
+ NAME
2
+ testy.rb
3
+
4
+ DESCRIPTION
5
+ a BDD testing framework for ruby that's mad at the world and plans to kick
6
+ it's ass in 80 freakin lines of code
7
+
8
+ SYNOPSIS
9
+ Testy.testing 'your code' do
10
+ test 'some behaviour' do |result|
11
+ ultimate = Ultimate.new
12
+ result.check :name, :expect => 42, :actual => ultimate.answer
13
+ end
14
+ end
15
+
16
+ PRINCIPLES AND GOALS
17
+ . it.should.not.merely.be.a.unit.testing.with.a.clever.dsl
18
+
19
+ . testing should not require learning a framework. ruby is a great
20
+ framework so testy uses it instead, requiring programmers learn exactly 2
21
+ new method calls
22
+
23
+ . testing loc should not dwarf those of the application
24
+
25
+ . testing framework loc should not dwarf those of the application
26
+
27
+ . testing frameworks should *never* alter ruby built-ins nor add methods to
28
+ Object, Kernel, .et al
29
+
30
+ . the output of tests should be machine parsable for reporting and ci tools
31
+ to easily integrate with
32
+
33
+ . the output of tests should be beautiful so that humans can read it
34
+
35
+ . the shape of the test file should not insult the programmer so that tests
36
+ can double as sample code
37
+
38
+ . the testing framework should never alter exception semantics
39
+
40
+ . hi-jacking at_exit sucks ass
41
+
42
+ . the exit status of running a test suite should indicate the degree of it's
43
+ failure state: the more failures the higher the exit status
44
+
45
+ . sample code should easily be able to double as a test suite, including
46
+ it's output
47
+
48
+ . testing should improve your code and help your users, not make you want to
49
+ kill yourself
50
+
51
+ . using a format that aligns in terminal is sanity saving when comparing
52
+ output
53
+
54
+ . testing frameworks should provide as few shortcuts for making brittle
55
+ tightly coupled tests as possible
56
+
57
+ . test suites should be able to be created, manipulated, have their output
58
+ streamed to different ports, and even tested themselves - they should be
59
+ plain ol objects under the hood
60
+
61
+ SAMPLES
62
+
63
+ <========< samples/a.rb >========>
64
+
65
+ ~ > cat samples/a.rb
66
+
67
+ # simple use of testy involves simply writing code, and recording the result
68
+ # you expect against the actual result
69
+ #
70
+ # notice that the output is very pretty and that the exitstatus is 0 when all
71
+ # tests pass
72
+ #
73
+ require 'testy'
74
+
75
+ Testy.testing 'the kick-ass-ed-ness of testy' do
76
+
77
+ test 'the ultimate answer to life' do |result|
78
+ list = []
79
+
80
+ list << 42
81
+ result.check :a, :expect => 42, :actual => list.first
82
+
83
+ list << 42.0
84
+ result.check :b, 42.0, list.last
85
+ end
86
+
87
+ end
88
+
89
+ ~ > ruby samples/a.rb #=> exitstatus=0
90
+
91
+ ---
92
+ the kick-ass-ed-ness of testy:
93
+ the ultimate answer to life:
94
+ success:
95
+ a: 42
96
+ b: 42.0
97
+
98
+
99
+ <========< samples/b.rb >========>
100
+
101
+ ~ > cat samples/b.rb
102
+
103
+ # testy will handle unexpected results and exceptions thrown in your code in
104
+ # exactly the same way - by reporting on them in a beautiful fashion and
105
+ # continuing to run other tests. notice, however, that an unexpected result
106
+ # or raised exception will cause a non-zero exitstatus (equalling the number
107
+ # of failed tests) for the suite as a whole. also note that previously
108
+ # accumulate expect/actual pairs are still reported on in the error report.
109
+ #
110
+ require 'testy'
111
+
112
+ Testy.testing 'the exception handling of testy' do
113
+
114
+ test 'raising an exception' do |result|
115
+ list = []
116
+
117
+ list << 42
118
+ result.check :a, :expect => 42, :actual => list.first
119
+
120
+ list.method_that_does_not_exist
121
+ end
122
+
123
+ test 'returning unexpected results' do |result|
124
+ result.check 'a', 42, 42
125
+ result.check :b, :expect => 'forty-two', :actual => 42.0
126
+ end
127
+
128
+ end
129
+
130
+ ~ > ruby samples/b.rb #=> exitstatus=2
131
+
132
+ ---
133
+ the exception handling of testy:
134
+ raising an exception:
135
+ failure:
136
+ error:
137
+ class: NoMethodError
138
+ message: undefined method `method_that_does_not_exist' for [42]:Array
139
+ backtrace:
140
+ - samples/b.rb:18
141
+ - ./lib/testy.rb:65:in `call'
142
+ - ./lib/testy.rb:65:in `run'
143
+ - /opt/local/lib/ruby/site_ruby/1.8/orderedhash.rb:65:in `each'
144
+ - /opt/local/lib/ruby/site_ruby/1.8/orderedhash.rb:65:in `each'
145
+ - ./lib/testy.rb:61:in `run'
146
+ - ./lib/testy.rb:89:in `testing'
147
+ - samples/b.rb:10
148
+ expect:
149
+ a: 42
150
+ actual:
151
+ a: 42
152
+ returning unexpected results:
153
+ failure:
154
+ expect:
155
+ a: 42
156
+ b: forty-two
157
+ actual:
158
+ a: 42
159
+ b: 42.0
160
+
@@ -0,0 +1,40 @@
1
+ #! /usr/bin/env gem build
2
+
3
+ require 'rubygems'
4
+
5
+ Gem::Specification::new do |spec|
6
+ $VERBOSE = nil
7
+
8
+ shiteless = lambda do |list|
9
+ list.delete_if do |file|
10
+ file =~ %r/\.git/ or
11
+ file =~ %r/\.svn/ or
12
+ file =~ %r/\.tmp/
13
+ end
14
+ end
15
+
16
+ spec.name = $lib
17
+ spec.version = $version
18
+ spec.platform = Gem::Platform::RUBY
19
+ spec.summary = $lib
20
+
21
+ spec.files = shiteless[Dir::glob("**/**")]
22
+ spec.executables = shiteless[Dir::glob("bin/*")].map{|exe| File::basename(exe)}
23
+
24
+ spec.require_path = "lib"
25
+
26
+ spec.has_rdoc = true
27
+ spec.add_dependency 'orderedhash'
28
+
29
+ spec.author = "Ara T. Howard"
30
+ spec.email = "ara.t.howard@gmail.com"
31
+ spec.homepage = "http://github.com/ahoward/testy/tree/master"
32
+ end
33
+
34
+
35
+ BEGIN{
36
+ Dir.chdir(File.dirname(__FILE__))
37
+ $lib = 'testy'
38
+ Kernel.load "./lib/#{ $lib }.rb"
39
+ $version = Testy.version
40
+ }
@@ -0,0 +1,43 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require 'pathname'
4
+
5
+ $VERBOSE=nil
6
+
7
+ def indent s, n = 2
8
+ ws = ' ' * n
9
+ s.gsub %r/^/, ws
10
+ end
11
+
12
+ template = IO::read 'README.tmpl'
13
+
14
+ samples = ''
15
+ prompt = '~ > '
16
+
17
+ Dir['sample*/*'].sort.each do |sample|
18
+ samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
19
+
20
+ cmd = "cat #{ sample }"
21
+ samples << indent(prompt + cmd, 2) << "\n\n"
22
+ samples << indent(`#{ cmd }`, 4) << "\n"
23
+
24
+ cmd = "ruby #{ sample }"
25
+ #samples << indent(prompt + cmd, 2) << "\n\n"
26
+
27
+ cmd = "ruby -e'STDOUT.sync=true; exec %(ruby -Ilib #{ sample })'"
28
+ out = `#{ cmd } 2>&1`
29
+ #samples << indent(`#{ cmd } 2>&1`, 4) << "\n"
30
+
31
+ exitstatus = " #=> exitstatus=#{ $?.exitstatus }"
32
+ cmd = "ruby #{ sample }"
33
+ samples << indent(prompt + cmd + exitstatus, 2) << "\n\n"
34
+ samples << indent(out, 4) << "\n"
35
+
36
+ #samples << indent("\n#{ prompt } #{ $?.exitstatus } ### exitstatus\n")
37
+ end
38
+
39
+ #samples.gsub! %r/^/, ' '
40
+
41
+ readme = template.gsub %r/^\s*@samples\s*$/, samples
42
+ open('README', 'w'){|fd| fd.write readme}
43
+ print readme
@@ -0,0 +1,92 @@
1
+ require 'rubygems'
2
+ require 'orderedhash'
3
+ require 'yaml'
4
+
5
+ module Testy
6
+ def Testy.version() '0.4.2' end
7
+
8
+ class Test
9
+ class BadResult < StandardError
10
+ end
11
+
12
+ class OrderedHash < ::OrderedHash
13
+ def with_string_keys
14
+ oh = self.class.new
15
+ each_pair{|key, val| oh[key.to_s] = val}
16
+ oh
17
+ end
18
+ end
19
+
20
+ class Result
21
+ attr_accessor :expect
22
+ attr_accessor :actual
23
+
24
+ def initialize
25
+ @expect = OrderedHash.new
26
+ @actual = OrderedHash.new
27
+ end
28
+
29
+ def check(name, *args)
30
+ options = args.last.is_a?(Hash) ? args.pop : {}
31
+ value = args.size==0 ? (options[:expect]||options['expect']) : args.shift
32
+ expect[name.to_s] = value
33
+ value = args.size==0 ? (options[:actual]||options['actual']) : args.shift
34
+ actual[name.to_s] = value
35
+ end
36
+
37
+ def ok?
38
+ expect == actual
39
+ end
40
+ end
41
+
42
+ attr_accessor :name
43
+ attr_accessor :tests
44
+ attr_accessor :block
45
+
46
+ def initialize(*args, &block)
47
+ options = args.last.is_a?(Hash) ? args.pop : {}
48
+ @name = args.first || options[:name] || options['name']
49
+ @tests = OrderedHash.new
50
+ @block = block
51
+ end
52
+
53
+ def test(name, &block)
54
+ @tests[name.to_s] = block
55
+ end
56
+
57
+ def run port = STDOUT
58
+ instance_eval(&@block) if @block
59
+ report = OrderedHash.new
60
+ failures = 0
61
+ tests.each do |name, block|
62
+ result = Result.new
63
+ report[name] =
64
+ begin
65
+ block.call(result)
66
+ raise BadResult, name unless result.ok?
67
+ {'success' => result.actual}
68
+ rescue Object => e
69
+ failures += 1
70
+ failure = OrderedHash.new
71
+ unless e.is_a?(BadResult)
72
+ error = OrderedHash.new
73
+ error['class'] = e.class.name
74
+ error['message'] = e.message.to_s
75
+ error['backtrace'] = e.backtrace||[]
76
+ failure['error'] = error
77
+ end
78
+ failure['expect'] = result.expect
79
+ failure['actual'] = result.actual
80
+ {'failure' => failure}
81
+ end
82
+ end
83
+ port << {name => report}.to_yaml
84
+ failures
85
+ end
86
+ end
87
+
88
+ def Testy.testing(*args, &block)
89
+ failures = Test.new(*args, &block).run
90
+ exit(failures)
91
+ end
92
+ end
@@ -0,0 +1,21 @@
1
+ # simple use of testy involves simply writing code, and recording the result
2
+ # you expect against the actual result
3
+ #
4
+ # notice that the output is very pretty and that the exitstatus is 0 when all
5
+ # tests pass
6
+ #
7
+ require 'testy'
8
+
9
+ Testy.testing 'the kick-ass-ed-ness of testy' do
10
+
11
+ test 'the ultimate answer to life' do |result|
12
+ list = []
13
+
14
+ list << 42
15
+ result.check :a, :expect => 42, :actual => list.first
16
+
17
+ list << 42.0
18
+ result.check :b, 42.0, list.last
19
+ end
20
+
21
+ end
@@ -0,0 +1,26 @@
1
+ # testy will handle unexpected results and exceptions thrown in your code in
2
+ # exactly the same way - by reporting on them in a beautiful fashion and
3
+ # continuing to run other tests. notice, however, that an unexpected result
4
+ # or raised exception will cause a non-zero exitstatus (equalling the number
5
+ # of failed tests) for the suite as a whole. also note that previously
6
+ # accumulate expect/actual pairs are still reported on in the error report.
7
+ #
8
+ require 'testy'
9
+
10
+ Testy.testing 'the exception handling of testy' do
11
+
12
+ test 'raising an exception' do |result|
13
+ list = []
14
+
15
+ list << 42
16
+ result.check :a, :expect => 42, :actual => list.first
17
+
18
+ list.method_that_does_not_exist
19
+ end
20
+
21
+ test 'returning unexpected results' do |result|
22
+ result.check 'a', 42, 42
23
+ result.check :b, :expect => 'forty-two', :actual => 42.0
24
+ end
25
+
26
+ end
File without changes
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: testy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.2
5
+ platform: ruby
6
+ authors:
7
+ - Ara T. Howard
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-28 00:00:00 -06:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: orderedhash
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description:
26
+ email: ara.t.howard@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files: []
32
+
33
+ files:
34
+ - gemspec.rb
35
+ - gen_readme.rb
36
+ - lib
37
+ - lib/testy.rb
38
+ - README
39
+ - samples
40
+ - samples/a.rb
41
+ - samples/b.rb
42
+ - testy-0.4.2.gem
43
+ has_rdoc: true
44
+ homepage: http://github.com/ahoward/testy/tree/master
45
+ post_install_message:
46
+ rdoc_options: []
47
+
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ requirements: []
63
+
64
+ rubyforge_project:
65
+ rubygems_version: 1.3.1
66
+ signing_key:
67
+ specification_version: 2
68
+ summary: testy
69
+ test_files: []
70
+