joshng-zebra 0.1.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.rdoc +61 -0
- data/VERSION.yml +4 -0
- data/lib/zebra/shoulda.rb +42 -0
- data/lib/zebra.rb +49 -0
- data/test/context/context_test.rb +21 -0
- data/test/else/matchy_test.rb +13 -0
- data/test/shoulda/shoulda_test.rb +26 -0
- data/test/test_helper.rb +7 -0
- metadata +92 -0
data/README.rdoc
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
= Zebra
|
2
|
+
|
3
|
+
One line tests without the smells.
|
4
|
+
|
5
|
+
= The problem
|
6
|
+
|
7
|
+
context "A blog post" do
|
8
|
+
setup do
|
9
|
+
@author = create_person
|
10
|
+
@post = create_post :author => @author
|
11
|
+
end
|
12
|
+
|
13
|
+
should "be editable by its author" do
|
14
|
+
assert @post.editable_by?(@author)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
== Don't see the problem?
|
19
|
+
|
20
|
+
Why bother writing self-documenting test code if you always have to explain it to the reader? {Test names are essentially glorified comments}[http://blog.jayfields.com/2008/05/testing-value-of-test-names.html] and {comments are frequently code smells}[http://memeagora.blogspot.com/2008/11/comments-code-smell.html]. Furthermore, all the extra code required to create a test (should "" do ... end) almost certainly discourages one assertion per test. If the assertion is one line and the code can explain itself, why bother with all the other crap?
|
21
|
+
|
22
|
+
== The Solution
|
23
|
+
|
24
|
+
context "With a blog post" do
|
25
|
+
setup do
|
26
|
+
@author = create_person
|
27
|
+
@somebody_else = create_person
|
28
|
+
@post = create_post :author => @author
|
29
|
+
end
|
30
|
+
|
31
|
+
expect { @post.to be_editable_by(@author) }
|
32
|
+
expect { @post.not_to be_editable_by(@somebody_else) }
|
33
|
+
end
|
34
|
+
|
35
|
+
== But, what about the test name?
|
36
|
+
|
37
|
+
I'm glad you asked. This is where zebra gets really cool. The above test will create tests with the following names:
|
38
|
+
|
39
|
+
test: With a blog post expect @post.to(be_editable_by(@author))
|
40
|
+
test: With a blog post expect @post.not_to(be_editable_by(@author))
|
41
|
+
|
42
|
+
Now, *that* is self documenting code.
|
43
|
+
|
44
|
+
== The right tool for the job
|
45
|
+
|
46
|
+
The cool thing about zebra is that it's an extension to test/unit. If you have a test that belongs in a should block, with a big, old-fashioned test name, you can have it. Just use should or it. When you have a short, self-documenting test, use expect. Best of both worlds.
|
47
|
+
|
48
|
+
== Dependencies
|
49
|
+
|
50
|
+
- jeremymcanally-context or shoulda
|
51
|
+
- jeremymcanally-matchy
|
52
|
+
- parse_tree
|
53
|
+
- ruby2ruby
|
54
|
+
|
55
|
+
== Inspiration
|
56
|
+
|
57
|
+
{Jay Fields' Expectations}[http://blog.jayfields.com/2007/12/ruby-expectation-gem.html]
|
58
|
+
|
59
|
+
== COPYRIGHT
|
60
|
+
|
61
|
+
Copyright (c) 2008 {James Golick}[http://jamesgolick.com]. See LICENSE for details.
|
data/VERSION.yml
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module Zebra
|
2
|
+
module ShouldaSupport
|
3
|
+
def self.included(klass)
|
4
|
+
klass.class_eval do
|
5
|
+
attr_accessor :expects
|
6
|
+
|
7
|
+
alias_method :build_without_expects, :build
|
8
|
+
alias_method :build, :build_with_expects
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def expect(&block)
|
13
|
+
self.expects ||= []
|
14
|
+
self.expects << block
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_test_from_expect(&block)
|
18
|
+
test_name = expect_test_name(full_name, &block)
|
19
|
+
|
20
|
+
if test_unit_class.instance_methods.include?(test_name.to_s)
|
21
|
+
warn " * WARNING: '#{test_name}' is already defined"
|
22
|
+
end
|
23
|
+
|
24
|
+
context = self
|
25
|
+
test_unit_class.send(:define_method, test_name) do
|
26
|
+
begin
|
27
|
+
context.run_parent_setup_blocks(self)
|
28
|
+
context.run_current_setup_blocks(self)
|
29
|
+
block.bind(self).call
|
30
|
+
ensure
|
31
|
+
context.run_all_teardown_blocks(self)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def build_with_expects
|
37
|
+
(expects || []).each { |e| create_test_from_expect(&e) }
|
38
|
+
build_without_expects
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
data/lib/zebra.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'matchy'
|
3
|
+
require 'parse_tree'
|
4
|
+
require 'parse_tree_extensions'
|
5
|
+
require 'ruby2ruby'
|
6
|
+
require File.dirname(__FILE__) + '/zebra/shoulda'
|
7
|
+
|
8
|
+
module Zebra
|
9
|
+
class << self
|
10
|
+
def shoulda?
|
11
|
+
defined?(Shoulda)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def expect(&block)
|
16
|
+
Zebra.shoulda? ? expect_shoulda(&block) : expect_context(&block)
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
def expect_shoulda(&block)
|
21
|
+
Shoulda::Context.send(:include, Zebra::ShouldaSupport) unless Shoulda::Context.include?(Zebra::ShouldaSupport)
|
22
|
+
|
23
|
+
if Shoulda.current_context
|
24
|
+
Shoulda.current_context.expect(&block)
|
25
|
+
else
|
26
|
+
context_name = self.name.gsub(/Test/, "")
|
27
|
+
context = Shoulda::Context.new(context_name, self) do
|
28
|
+
expect(&block)
|
29
|
+
end
|
30
|
+
context.build
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def expect_context(&block)
|
35
|
+
define_method(expect_test_name(context_name, &block), &block)
|
36
|
+
end
|
37
|
+
|
38
|
+
def expect_test_name(context_name, &block)
|
39
|
+
block_translation = block.to_ruby.gsub /proc \{ (.+?) \}/, '\1'
|
40
|
+
test_name = ["test:", context_name, "expect", block_translation]
|
41
|
+
test_name.reject! { |s| s == "" }
|
42
|
+
|
43
|
+
test_name.join(' ')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
Test::Unit::TestCase.send(:extend, Zebra)
|
48
|
+
Object.send(:alias_method, :to, :should)
|
49
|
+
Object.send(:alias_method, :not_to, :should_not)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
require 'context'
|
3
|
+
|
4
|
+
class ContextTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
Zebra.stubs(:shoulda?).returns(false)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should create a test" do
|
10
|
+
self.class.expect { 2.to == 1 }
|
11
|
+
assert self.respond_to?("test: expect (2.to == 1)")
|
12
|
+
end
|
13
|
+
|
14
|
+
context "in a context" do
|
15
|
+
it "should grab the name of the context" do
|
16
|
+
self.class.expect { 2.to == 1 }
|
17
|
+
assert self.respond_to?("test: in a context expect (2.to == 1)"), self.class.instance_methods.grep(/test/).inspect
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
require 'context'
|
3
|
+
|
4
|
+
class MatchyTest < Test::Unit::TestCase
|
5
|
+
it "should alias should to .to" do
|
6
|
+
assert_equal Object.method(:should), Object.method(:to)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should alias should_not to .not_to" do
|
10
|
+
assert_equal Object.method(:should_not), Object.method(:not_to)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
require 'shoulda'
|
3
|
+
|
4
|
+
class ShouldaTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
Zebra.stubs(:shoulda?).returns(true)
|
7
|
+
end
|
8
|
+
|
9
|
+
should "create a test" do
|
10
|
+
self.class.expect { 2.to == 1 }
|
11
|
+
assert self.respond_to?("test: Shoulda expect (2.to == 1)"), self.class.instance_methods.grep(/test/).inspect
|
12
|
+
end
|
13
|
+
|
14
|
+
context "in a context" do
|
15
|
+
expect { true }
|
16
|
+
should "grab the name of the context" do
|
17
|
+
assert self.respond_to?("test: in a context expect true"), self.class.instance_methods.grep(/test/).inspect
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "A context with no expects" do
|
22
|
+
should "not raise any exceptions" do
|
23
|
+
true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: joshng-zebra
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Golick
|
8
|
+
- Josh Gruenberg
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2009-02-10 00:00:00 -08:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: jeremymcanally-matchy
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.1
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: ParseTree
|
27
|
+
version_requirement:
|
28
|
+
version_requirements: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 3.0.2
|
33
|
+
version:
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: ruby2ruby
|
36
|
+
version_requirement:
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 1.2.1
|
42
|
+
version:
|
43
|
+
description: TODO
|
44
|
+
email: joshngru@gmail.com
|
45
|
+
executables: []
|
46
|
+
|
47
|
+
extensions: []
|
48
|
+
|
49
|
+
extra_rdoc_files: []
|
50
|
+
|
51
|
+
files:
|
52
|
+
- README.rdoc
|
53
|
+
- VERSION.yml
|
54
|
+
- lib/zebra
|
55
|
+
- lib/zebra/shoulda.rb
|
56
|
+
- lib/zebra.rb
|
57
|
+
- test/context
|
58
|
+
- test/context/context_test.rb
|
59
|
+
- test/else
|
60
|
+
- test/else/matchy_test.rb
|
61
|
+
- test/shoulda
|
62
|
+
- test/shoulda/shoulda_test.rb
|
63
|
+
- test/test_helper.rb
|
64
|
+
has_rdoc: true
|
65
|
+
homepage: http://github.com/joshng/zebra
|
66
|
+
post_install_message:
|
67
|
+
rdoc_options:
|
68
|
+
- --inline-source
|
69
|
+
- --charset=UTF-8
|
70
|
+
require_paths:
|
71
|
+
- lib
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: "0"
|
77
|
+
version:
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: "0"
|
83
|
+
version:
|
84
|
+
requirements: []
|
85
|
+
|
86
|
+
rubyforge_project:
|
87
|
+
rubygems_version: 1.2.0
|
88
|
+
signing_key:
|
89
|
+
specification_version: 2
|
90
|
+
summary: TODO
|
91
|
+
test_files: []
|
92
|
+
|