testy 0.4.2

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,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
+