lookout 2.1.4 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,18 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  Expectations do
4
- expect true do
5
- Lookout::Results::Unsuccessful.new.tap{ |results|
6
- Lookout::Expectations.new(results)
7
- }.succeeded?
8
- end
9
-
10
- expect false do
11
- Lookout::Results::Unsuccessful.new.tap{ |results|
12
- Lookout::Expectations.new(results).expect(1){ 2 }
13
- }.succeeded?
14
- end
15
-
16
4
  expect 3 do
17
5
  Lookout::Results::Unsuccessful.new.tap{ |results|
18
6
  Lookout::Expectations.new(results).
@@ -22,32 +10,6 @@ Expectations do
22
10
  }.count
23
11
  end
24
12
 
25
- expect 1 do
26
- Lookout::Results::Unsuccessful.new.tap{ |results|
27
- expectations = Lookout::Expectations.new(results, __LINE__ + 1)
28
- expectations.expect(1){ 2 }
29
- expectations.expect(1){ 2 }
30
- }.count
31
- end
32
-
33
- expect 1 do
34
- Lookout::Results::Unsuccessful.new.tap{ |results|
35
- expectations = Lookout::Expectations.new(results, __LINE__ + 1)
36
- expectations.expect(1){ 2 }
37
- expectations.expect(1){ 2 }
38
- expectations.flush
39
- }.count
40
- end
41
-
42
- expect 1 do
43
- Lookout::Results::Unsuccessful.new.tap{ |results|
44
- expectations = Lookout::Expectations.new(results, __LINE__ + 2)
45
- expectations.expect(1){ 2 }
46
- expectations.expect(1){ 2 }
47
- expectations.flush
48
- }.count
49
- end
50
-
51
13
  expect __LINE__ + 2 do
52
14
  Lookout::Results::Unsuccessful.new.tap{ |results|
53
15
  Lookout::Expectations.new(results).expect(1){ 2 }
@@ -0,0 +1,29 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Expectations do
4
+ expect 1 do
5
+ Lookout::Results::Unsuccessful.new.tap{ |results|
6
+ expectations = Lookout::Expectations::Line.new(__LINE__ + 1, results)
7
+ expectations.expect(1){ 2 }
8
+ expectations.expect(1){ 2 }
9
+ }.count
10
+ end
11
+
12
+ expect 1 do
13
+ Lookout::Results::Unsuccessful.new.tap{ |results|
14
+ expectations = Lookout::Expectations::Line.new(__LINE__ + 1, results)
15
+ expectations.expect(1){ 2 }
16
+ expectations.expect(1){ 2 }
17
+ expectations.flush
18
+ }.count
19
+ end
20
+
21
+ expect 1 do
22
+ Lookout::Results::Unsuccessful.new.tap{ |results|
23
+ expectations = Lookout::Expectations::Line.new(__LINE__ + 2, results)
24
+ expectations.expect(1){ 2 }
25
+ expectations.expect(1){ 2 }
26
+ expectations.flush
27
+ }.count
28
+ end
29
+ end
@@ -0,0 +1,20 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Expectations do
4
+ expect "\tfrom 1
5
+ \tfrom 2
6
+ \tfrom 3
7
+ \tfrom 4
8
+ \tfrom 5
9
+ \tfrom 6
10
+ \tfrom 7
11
+ \tfrom 8
12
+ \t ... 6 levels ...
13
+ \tfrom A
14
+ \tfrom B
15
+ \tfrom C
16
+ \tfrom D
17
+ \tfrom E" do
18
+ Lookout::Results::Error::Exception::Backtrace.new(%w[1 2 3 4 5 6 7 8 a b c d e f A B C D E], true, false).to_s
19
+ end
20
+ end
@@ -6,19 +6,4 @@ Expectations do
6
6
  results << Lookout::Results::Fulfilled.new(nil, 0)
7
7
  results.count
8
8
  end
9
-
10
- expect Lookout::Results::Unsuccessful.new.not.to.have.succeeded? do |results|
11
- results << Lookout::Results::Failures::State.new(nil, 0, nil)
12
- results << Lookout::Results::Fulfilled.new(nil, 0)
13
- end
14
-
15
- expect Lookout::Results::Unsuccessful.new.not.to.have.succeeded? do |results|
16
- results << Lookout::Results::Failures::Behavior.new(nil, 0, nil)
17
- results << Lookout::Results::Fulfilled.new(nil, 0)
18
- end
19
-
20
- expect Lookout::Results::Unsuccessful.new.to.have.succeeded? do |results|
21
- results << Lookout::Results::Fulfilled.new(nil, 0)
22
- results << Lookout::Results::Fulfilled.new(nil, 0)
23
- end
24
9
  end
@@ -0,0 +1,30 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Expectations do
4
+ expect false do
5
+ Lookout::Runners::Trackers::Failure.new(Lookout::Results.new).failed?
6
+ end
7
+
8
+ expect true do
9
+ results = Lookout::Results.new
10
+ failed = Lookout::Runners::Trackers::Failure.new(results)
11
+ results << Lookout::Results::Failures::State.new(nil, 0, nil)
12
+ failed.failed?
13
+ end
14
+
15
+ expect true do
16
+ results = Lookout::Results.new
17
+ failed = Lookout::Runners::Trackers::Failure.new(results)
18
+ results << Lookout::Results::Failures::State.new(nil, 0, nil)
19
+ results << Lookout::Results::Fulfilled.new(nil, 0)
20
+ failed.failed?
21
+ end
22
+
23
+ expect true do
24
+ results = Lookout::Results.new
25
+ failed = Lookout::Runners::Trackers::Failure.new(results)
26
+ results << Lookout::Results::Fulfilled.new(nil, 0)
27
+ results << Lookout::Results::Failures::State.new(nil, 0, nil)
28
+ failed.failed?
29
+ end
30
+ end
@@ -1,5 +1,4 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  Expectations do
4
-
5
4
  end
metadata CHANGED
@@ -1,509 +1,498 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: lookout
3
- version: !ruby/object:Gem::Version
4
- hash: 3
5
- prerelease: false
6
- segments:
7
- - 2
8
- - 1
9
- - 4
10
- version: 2.1.4
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.2.0
5
+ prerelease:
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Nikolai Weibull
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-07-26 00:00:00 +02:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
12
+ date: 2011-10-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
22
15
  name: yard
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &14599272 !ruby/object:Gem::Requirement
25
17
  none: false
26
- requirements:
18
+ requirements:
27
19
  - - ~>
28
- - !ruby/object:Gem::Version
29
- hash: 7
30
- segments:
31
- - 0
32
- - 6
33
- - 0
20
+ - !ruby/object:Gem::Version
34
21
  version: 0.6.0
35
22
  type: :development
36
- version_requirements: *id001
37
- description: "# Lookout #\n\n\
38
- Lookout is a lightweight unit testing framework. Tests (expectations) can be\n\
39
- written as follows\n\n expect 2 do\n 1 + 1\n end\n\n expect NoMethodError do\n Object.invalid_method_call\n end\n\n\
40
- Lookout is designed to encourage \xE2\x80\x93 force, even \xE2\x80\x93 unit testing best practices\n\
41
- such as\n\n * Setting up only one expectation per test\n * Not setting expectations on non-public APIs\n * Test isolation\n\n\
42
- This is done by\n\n * Only allowing one expectation to be set per test\n * Providing no (additonal) way of accessing private state\n * Providing no setup and teardown methods, nor a method of providing test\n helpers\n\n\
43
- Other important points are\n\n * A unified syntax for setting up both state-based and behavior-based\n expectations\n * A focus on code readability by providing no mechanism for describing an\n expectation other than the code in the expectation itself\n\n\
44
- The way Lookout works has been heavily influenced by [expectations], by [Jay\n\
45
- Fields][]. The code base was once also heavily based on [expectations],\n\
46
- based at Subversion [revision r76][]. A lot has happened since then and all of the\n\
47
- work past that revision are due to [Nikolai Weibull][].\n\n\
48
- [expectations]: http://expectations.rubyforge.org\n\
49
- [Jay Fields]: http://blog.jayfields.com\n\
50
- [revision r76]: https://github.com/now/lookout/commit/537bedf3e5b3eb4b31c066b3266f42964ac35ebe\n\
51
- [Nikolai Weibull]: http://bitwi.se\n\n\n\
52
- ## Installation ##\n\n\
53
- Install Lookout with\n\n % gem install lookout\n\n\n\
54
- ## Usage ##\n\n\
55
- Lookout allows you to set expectations on an object\xE2\x80\x99s state or behavior. We\xE2\x80\x99ll\n\
56
- begin by looking at state expectations and then take a look at expectations on\n\
57
- behavior.\n\n\
58
- ### Expectations on State ###\n\n\
59
- An expectation can be made on the result of a computation:\n\n expect 2 do\n 1 + 1\n end\n\n\
60
- Most objects, in fact, have their state expectations checked by invoking `#==`\n\
61
- on the expected value with the result as its argument.\n\n\
62
- Checking that a result is within a given range is also simple:\n\n expect 0.099..0.101 do\n 0.4 - 0.3\n end\n\n\
63
- Here, the more general `#===` is being used on the `Range`.\n\n\
64
- `Strings` of course match against `Strings`:\n\n expect 'ab' do\n 'abc'[0..1]\n end\n\n\
65
- but we can also match a `String` against a `Regexp`:\n\n expect %r{a substring} do\n 'a string with a substring'\n end\n\n\
66
- (Please note the use of `%r{\xE2\x80\xA6}` to avoid warnings that will be generated when\n\
67
- Ruby parses `expect /\xE2\x80\xA6/`.)\n\n\
68
- Checking that the result includes a certain module is done by expecting the\n\
69
- `Module`.\n\n expect Enumerable do\n []\n end\n\n\
70
- This, due to the nature of Ruby, of course also works for classes (as they are\n\
71
- also modules):\n\n expect String do\n 'a string'\n end\n\n\
72
- This doesn\xE2\x80\x99t hinder us from expecting the actual `Module` itself:\n\n expect Enumerable do\n Enumerable\n end\n\n\
73
- As you may have figured out yourself, this is accomplished by first trying\n\
74
- `#==` and, if it returns `false`, then trying `#===` on the expected `Module`.\n\
75
- This is also true of `Ranges` and `Regexps`.\n\n\
76
- Truthfulness is expected with `true` and `false`:\n\n expect true do\n 1\n end\n\n expect false do\n nil\n end\n\n\
77
- Results equaling `true` or `false` are slightly different:\n\n expect TrueClass do\n true\n end\n\n expect FalseClass do\n false\n end\n\n\
78
- The rationale for this is that you should only care if the result of a\n\
79
- computation evaluates to a value that Ruby considers to be either true or\n\
80
- false, not the exact literals `true` or `false`.\n\n\
81
- Expecting output on an IO object is also common:\n\n expect output(\"abc\\ndef\\n\") do |io|\n io.puts 'abc', 'def'\n end\n\n\
82
- This can be used to capture the output of a formatter that takes an output\n\
83
- object as a parameter.\n\n\
84
- You should always be expecting errors from \xE2\x80\x93 and in, but that\xE2\x80\x99s a different\n\
85
- story \xE2\x80\x93 your code:\n\n expect NoMethodError do\n Object.no_method\n end\n\n\
86
- Often, not only the type of the error, but its description, is important to\n\
87
- check:\n\n expect StandardError.new('message') do\n raise StandardError.new('message')\n end\n\n\
88
- As with `Strings`, `Regexps` can be used to check the error description:\n\n expect StandardError.new(/mess/) do\n raise StandardError.new('message')\n end\n\n\
89
- (Note that some of Ruby\xE2\x80\x99s built-in error classes have slightly complicated\n\
90
- behavior and will not allow you to pass a `Regexp` as a parameter. `NameError`\n\
91
- is such a class. This may warrant further investigation into whether or not\n\
92
- this is a bug, but I\xE2\x80\x99ll leave that up to the reader to decide.)\n\n\
93
- Lookout further provides a fluent way of setting up expectations on boolean\n\
94
- results. An object can \xE2\x80\x9Cbe\xE2\x80\x9D\n\n expect Class.new{ attr_accessor :running; }.new.to.be.running do |process|\n process.running = true\n end\n\n\
95
- or \xE2\x80\x9Cnot be\xE2\x80\x9D\n\n expect Class.new{ attr_accessor :running; }.new.not.to.be.running do |process|\n process.running = false\n end\n\n\
96
- or to \xE2\x80\x9Chave\xE2\x80\x9D\n\n expect Class.new{ attr_accessor :finished; }.new.to.have.finished do |process|\n process.finished = true\n end\n\n\
97
- or \xE2\x80\x9Cnot have\xE2\x80\x9D\n\n expect Class.new{ attr_accessor :finished; }.new.not.to.have.finished do |process|\n process.finished = false\n end\n\n\
98
- On the same note\n\n expect nil.to.be.nil?\n\n\
99
- and\n\n expect Object.new.not.to.be.nil?\n\n\
100
- As not every boolean method \xE2\x80\x9Cis\xE2\x80\x9D or \xE2\x80\x9Chas\xE2\x80\x9D you can even\n\n expect nil.to.respond_to? :nil?\n\n\
101
- The rules here are that all `Objects` respond to `#to`. After `#to` you may\n\
102
- call\n\n * `#not`\n * `#be`\n * `#have`\n * Any method whose name ends with `?`\n\n\
103
- A call to `#not` must be followed by a call to one of the three alternatives\n\
104
- that follow it in the list. `#Be` and `#Have` must be followed by a call to a\n\
105
- method.\n\n\
106
- ### Expectations on Behavior ###\n\n\
107
- We expect our objects to be on their best behavior. Lookout allows you to make\n\
108
- sure that they are.\n\n\
109
- Mocks let use verify that a method is called in the way that we expect it to\n\
110
- be:\n\n expect mock.to.receive.dial('2125551212').twice do |phone|\n phone.dial('2125551212')\n phone.dial('2125551212')\n end\n\n\
111
- Here, `#mock` creates a mock object, an object that doesn\xE2\x80\x99t respond to\n\
112
- anything unless you tell it to. We tell it to expect to receive a call to\n\
113
- `#dail` with `'2125551212'` as its formal argument, and we expect it to receive\n\
114
- it twice. The mock object is then passed in to the block so that the\n\
115
- expectations placed upon it can be fulfilled.\n\n\
116
- Sometimes we only want to make sure that a method is called in the way that we\n\
117
- expect it to be, but we don\xE2\x80\x99t care if any other methods are called on the\n\
118
- object. A stub object, created with `#stub`, expects any method and returns a\n\
119
- stub object that, again, expects any method, and thus fits the bill.\n\n expect stub.to.receive.dial('2125551212').twice do |phone|\n phone.dial('2125551212')\n phone.hangup\n phone.dial('2125551212')\n end\n\n\
120
- We can also use stubs without any expectations on them:\n\n expect 3 do\n s = stub(:a => 1, :b => 2)\n s.a + s.b\n end\n\n\
121
- and we can stub out a specific method on an object:\n\n expect 'def' do\n a = 'abc'\n stub(a).to_str{ 'def' }\n a.to_str\n end\n\n\
122
- You don\xE2\x80\x99t have to use a mock object to verify that a method is called:\n\n expect Object.to.receive.deal do\n Object.deal\n end\n\n\
123
- As you have figured out by now, the expected method call is set up by calling\n\
124
- `#receive` after `#to`. `#Receive` is followed by a call to the method to\n\
125
- expect with any expected arguments. The body of the mocked method can be given\n\
126
- as the block to the method. Finally, an expected invocation count may follow\n\
127
- the method. Let\xE2\x80\x99s look at this formal specification in more detail.\n\n\
128
- The expected method arguments may be given in a variety of ways. Let\xE2\x80\x99s\n\
129
- introduce them by giving some examples:\n\n expect mock.to.receive.a do |m|\n \xE2\x80\xA6\n end\n\n\
130
- Here, the method `#a` must be called with any number of arguments. It may be\n\
131
- called any number of times, but it must be called at least once.\n\n\
132
- If a method must receive exactly one argument, you can use `arg`:\n\n expect mock.to.receive.a(arg) do |m|\n \xE2\x80\xA6\n end\n\n\
133
- If a method must receive a specific argument, you can use that argument:\n\n expect mock.to.receive.a(1..2) do |m|\n \xE2\x80\xA6\n end\n\n\
134
- The same matching rules apply for arguments as they do for state expectations,\n\
135
- so the previous example expects a call to `#a` with 1, 2, or the Range 1..2 as\n\
136
- an argument on `m`.\n\n\
137
- If a method must be invoked without any arguments you can use\n\
138
- `without_arguments`:\n\n expect mock.to.receive.a(without_arguments) do |m|\n \xE2\x80\xA6\n end\n\n\
139
- You can of course use both `arg` and actual arguments:\n\n expect mock.to.receive.a(arg, 1, arg) do |m|\n \xE2\x80\xA6\n end\n\n\
140
- The body of the mock method may be given as the block. Here, calling `#a` on\n\
141
- `m` will give the result `1`:\n\n expect mock.to.receive.a{ 1 } do |m|\n \xE2\x80\xA6\n end\n\n\
142
- If no body has been given, the result will be a stub object.\n\n\
143
- There is a caveat here in that a block can\xE2\x80\x99t yield in Ruby 1.8. To work around\n\
144
- this deficiency you have to use the `#yield` method:\n\n expect mock.to.receive.a.yield(1) do |m|\n \xE2\x80\xA6\n end\n\n\
145
- Any number of values to yield upon successive calls may be given. The last\n\
146
- value given will be used repeatedly when all preceding values have been\n\
147
- consumed. It\xE2\x80\x99s also important to know that values are splatted when they are\n\
148
- yielded.\n\n\
149
- To simulate an `#each`-like method you can use `#each`. The following horrible\n\
150
- example should give you an idea of how to use it.\n\n expect Object.new.to.receive.each.each(1, 2, 3) do |o|\n class << o\n include Enumerable\n end\n o.inject{ |i, a| i + a }\n end\n\n\
151
- Invocation count expectations can also be set if the default expectation of\n\
152
- \xE2\x80\x9Cat least once\xE2\x80\x9D isn\xE2\x80\x99t good enough. The following expectations are possible\n\n * `#at_most_once`\n * `#once`\n * `#at_least_once`\n * `#twice`\n\n\
153
- And, for a given `N`,\n\n * `#at_most(N)`\n * `#exactly(N)`\n * `#at_least(N)`\n\n\
154
- Method stubs are another useful thing to have in a unit testing framework.\n\
155
- Sometimes you need to override a method that does something a test shouldn\xE2\x80\x99t\n\
156
- do, like access and alter bank accounts. We can override \xE2\x80\x93 stub out \xE2\x80\x93 a method\n\
157
- by using the `#stub` method. Let\xE2\x80\x99s assume that we have an `Account` class that\n\
158
- has two methods, `#slips` and `#total`. `#Slips` retrieves the bank slips that\n\
159
- keep track of your deposits to the `Account` from a database. `#Total` sums\n\
160
- the `#slips`. In the following test we want to make sure that `#total` does\n\
161
- what it should do without accessing the database. We therefore stub out\n\
162
- `#slips` and make it return something that we can easily control.\n\n expect 6 do |m|\n account = Account.new\n stub(account).slips{ [1, 2, 3] }\n account.total\n end\n\n\
163
- As with mock methods, if no body is given, the result will be a stub object.\n\n\
164
- To make it easy to create objects with a set of stubbed methods there\xE2\x80\x99s also a\n\
165
- convenience method:\n\n expect 3 do\n s = stub(:a => 1, :b => 2)\n s.a + s.b\n end\n\n\
166
- Please note that this makes it impossible to stub a method on a Hash, but you\n\
167
- shouldn\xE2\x80\x99t be doing that anyway. In fact, you should never mock or stub methods\n\
168
- on value objects.\n\n\
169
- ## Integration ##\n\n\
170
- Lookout can be used from [Rake][]. Simply include the following code in your\n\
171
- `Rakefile`:\n\n require 'lookout/rake/tasks'\n\n Lookout::Rake::Tasks::Test.new\n\n\
172
- If the `:default` task hasn\xE2\x80\x99t been defined it will be set to depend on the\n\
173
- `:test` task.\n\n\
174
- As an added bonus you can use Lookouts own [gem][RubyGems] tasks:\n\n Lookout::Rake::Tasks::Gem.new\n\n\
175
- This provides tasks to `build`, `check`, `install`, and `push` your gem.\n\n\
176
- To use Lookout together with [Vim][], place `contrib/rakelookout.vim` in\n\
177
- `~/.vim/compiler` and add\n\n compiler rakelookout\n\n\
178
- to `~/.vim/after/ftplugin/ruby.vim`. Executing `:make` from inside [Vim][]\n\
179
- will now run your tests and an errors and failures can be visited with\n\
180
- `:cnext`. Execute `:help quickfix` for additional information.\n\n\
181
- Another useful addition to your `~/.vim/after/ftplugin/ruby.vim` file may be\n\n nnoremap <buffer> <silent> <Leader>M <Esc>:call <SID>run_test()<CR>\n let b:undo_ftplugin .= ' | nunmap <buffer> <Leader>M'\n\n function! s:run_test()\n let test = expand('%')\n let line = 'LINE=' . line('.')\n if test =~ '^lib/'\n let test = substitute(test, '^lib/', 'test/', '')\n let line = \"\"\n endif\n execute 'make' 'TEST=' . shellescape(test) line\n endfunction\n\n\
182
- Now, pressing `<Leader>M` will either run all tests for a given class, if the\n\
183
- implementation file is active, or run the test at or just before the cursor, if\n\
184
- the test file is active. This is useful if you\xE2\x80\x99re currently receiving a lot of\n\
185
- errors and/or failures and want to focus on those associated with a specific\n\
186
- class or on a specific test.\n\n\
187
- [Rake]: http://rake.rubyforge.org\n\
188
- [RubyGems]: http://rubygems.org\n\n\
189
- ## Interface Design ##\n\n\
190
- The default output of Lookout can Spartanly be described as Spartan. If no\n\
191
- errors or failures occur, no output is generated. This is unconventional, as\n\
192
- unit testing frameworks tend to dump a lot of information on the user,\n\
193
- concerning things such as progress, test count summaries, and flamboyantly\n\
194
- colored text telling you that your tests passed. None of this output is\n\
195
- needed. Your tests should run fast enough to not require progress reports.\n\
196
- The lack of output provides you with the same amount of information as\n\
197
- reporting success. Test count summaries are only useful if you\xE2\x80\x99re worried that\n\
198
- your tests aren\xE2\x80\x99t being run, but if you worry about that, then providing such\n\
199
- output doesn\xE2\x80\x99t really help. Testing your tests requires something beyond\n\
200
- reporting some arbitrary count that you would have to verify by hand anyway.\n\n\
201
- When errors or failures do occur, however, the relevant information is output\n\
202
- in a format that can easily be parsed by an `'errorformat'` for [Vim][] or with\n\
203
- [Compilation Mode][] for [Emacs][]. Diffs are generated for Strings, Arrays,\n\
204
- Hashes, and I/O.\n\n\
205
- [Vim]: http://www.vim.org\n\
206
- [Compilation Mode]: http://www.emacswiki.org/emacs/CompilationMode\n\
207
- [Emacs]: http://www.gnu.org/software/emacs/\n\n\
208
- ## External Design ##\n\n\
209
- Let\xE2\x80\x99s now look at some of the points made in the introduction in greater\n\
210
- detail.\n\n\
211
- Lookout only allows you to set one expectation per test. If you\xE2\x80\x99re testing\n\
212
- behavior with a mock, then only one method-invocation expectation can be set.\n\
213
- If you\xE2\x80\x99re testing state, then only one result can be verified. It may seem\n\
214
- like this would cause unnecessary duplication between tests. While this is\n\
215
- certainly a possibility, when you actually begin to try to avoid such\n\
216
- duplication you find that you often do so by improving your interfaces. This\n\
217
- kind of restriction tends to encourage the use of value objects, which are easy\n\
218
- to test, and more focused objects, which require simpler tests, as they have\n\
219
- less behavior to test, per method. By keeping your interfaces focused you\xE2\x80\x99re\n\
220
- also keeping your tests focused.\n\n\
221
- Keeping your tests focused improves, in itself, test isolation, but let\xE2\x80\x99s look\n\
222
- at something that hinders it: setup and teardown methods. Most unit testing\n\
223
- frameworks encourage test fragmentation by providing setup and teardown\n\
224
- methods.\n\n\
225
- Setup methods create objects and, perhaps, just their behavior for a set of\n\
226
- tests. This means that you have to look in two places to figure out what\xE2\x80\x99s\n\
227
- being done in a test. This may work fine for few methods with simple set-ups,\n\
228
- but makes things complicated when the number of tests increases and the set-up\n\
229
- is complex. Often, each test further adjusts the previously set-up object\n\
230
- before performing any verifications, further complicating the process of\n\
231
- figuring out what state an object has in a given test.\n\n\
232
- Teardown methods clean up after tests, perhaps by removing records from a\n\
233
- database or deleting files from the file-system. \n\n\
234
- The duplication that setup methods and teardown methods hope to remove is\n\
235
- better avoided by improving your interfaces. This can be done by providing\n\
236
- better set-up methods for your objects and using idioms such as [Resource\n\
237
- Acquisition Is Initialization][] for guaranteed clean-up, test or no test.\n\n\
238
- By not using setup and teardown methods we keep everything pertinent to a test\n\
239
- in the test itself, thus improving test isolation. (You also won\xE2\x80\x99t [slow down\n\
240
- your tests][Broken Test::Unit] by keeping unnecessary state.)\n\n\
241
- Most unit test frameworks also allow you to create arbitrary test helper\n\
242
- methods. Lookout doesn\xE2\x80\x99t. The same rationale as that that has been\n\
243
- crystallized in the preceding paragraphs applies. If you need helpers you\xE2\x80\x99re\n\
244
- interface isn\xE2\x80\x99t good enough. It really is as simple as that.\n\n\
245
- To clarify: there\xE2\x80\x99s nothing inherently wrong with test helper methods, but they\n\
246
- should be general enough that they reside in their own library. The support\n\
247
- for mocks in Lookout is provided through a set of test helper methods that make\n\
248
- it easier to create mocks than it would have been without them.\n\
249
- [Lookout-rack][] is another example of a library providing test helper methods\n\
250
- (well, one of method, actually) that are very useful in testing web\n\
251
- applications that use [Rack][].\n\n\
252
- A final point at which some unit test frameworks try to fragment tests further\n\
253
- is documentation. These frameworks provide ways of describing the whats and\n\
254
- hows of what\xE2\x80\x99s being tested, the rationale being that this will provide\n\
255
- documentation of both the test and the code being tested. Describing how a\n\
256
- stack data structure is meant to work is a common example. A stack is,\n\
257
- however, a rather simple data structure, so such a description provides little,\n\
258
- if any, additional information that can\xE2\x80\x99t be extracted from the implementation\n\
259
- and its tests themselves. The implementation and its tests is, in fact, its\n\
260
- own best documentation. Taking the points made in the previous paragraphs into\n\
261
- account, we should already have simple, self-describing, interfaces that have\n\
262
- easily understood tests associated with them. Rationales for the use of a\n\
263
- given data structure or system-design design documentation is better suited in\n\
264
- separate documentation focused at describing exactly those issues.\n\n\
265
- [Resource Acquisition Is Initialization]: http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization\n\
266
- [Broken Test::Unit]: http://37signals.com/svn/posts/2742-the-road-to-faster-tests\n\
267
- [Lookout-rack]: http://github.com/now/lookout-rack\n\
268
- [Rack]: http://rack.rubyforge.org\n\n\
269
- ## Internal Design ##\n\n\
270
- The internal design of Lookout has had a couple of goals.\n\n * As few external dependencies as possible\n * As few internal dependencies as possible\n * Internal extensibility provides external extensibility\n * As fast load times as possible\n * As high a ratio of value objects to mutable objects as possible\n * Each object must have a simple, obvious name\n * Use mix-ins, not inheritance for shared behavior\n * As few responsibilities per object as possible\n * Optimizing for speed can only be done when you have all the facts\n\n\
271
- ### External Dependencies ###\n\n\
272
- Lookout used to depend on Mocha for mocks and stubs. While benchmarking I\n\
273
- noticed that a method in Mocha was taking up more than 300 percent of the\n\
274
- runtime. It turned out that Mocha\xE2\x80\x99s method for cleaning up back-traces\n\
275
- generated when a mock failed was doing something incredibly stupid:\n\n backtrace.reject{ |l| Regexp.new(@lib).match(File.expand_path(l)) }\n\n\
276
- Here `@lib` is a `String` containing the path to the lib subdirectory in the\n\
277
- Mocha installation directory. I reported it, provided a patch five days later,\n\
278
- then waited. Nothing happened. 254 days later, according to [Wolfram\n\
279
- Alpha][254 days], half of my patch was, apparently \xE2\x80\x93 I say \xE2\x80\x9Capparently\xE2\x80\x9D, as I\n\
280
- received no notification \xE2\x80\x93 applied. By that time I had replaced the whole\n\
281
- mocking-and-stubbing subsystem and dropped the dependency.\n\n\
282
- Many Ruby developers claim that Ruby and its gems are too fast-moving for\n\
283
- normal package-managing systems to keep up. This is testament to the fact\n\
284
- that this isn\xE2\x80\x99t the case and that the real problem is instead related to sloppy\n\
285
- practices.\n\n\
286
- Please note that I don\xE2\x80\x99t want to single out the Mocha library nor its\n\
287
- developers. I only want to provide an example where relying on external\n\
288
- dependencies can be \xE2\x80\x9Cconsidered harmful\xE2\x80\x9D.\n\n\
289
- [254 days]: http://www.wolframalpha.com/input/?i=days+between+march+17%2C+2010+and+november+26%2C+2010\n\n\
290
- ### Internal Dependencies ###\n\n\
291
- Lookout has been designed so as to keep each subsystem independent of any\n\
292
- other. The diff subsystem is, for example, completely decoupled from any other\n\
293
- part of the system as a whole and could be moved into its own library at a time\n\
294
- where that would be of interest to anyone. What\xE2\x80\x99s perhaps more interesting is\n\
295
- that the diff subsystem is itself very modular. The data passes through a set\n\
296
- of filters that depends on what kind of diff has been requested, each filter\n\
297
- yielding modified data as it receives it. If you want to read some rather\n\
298
- functional Ruby I can highly recommend looking at the code in the\n\
299
- `lib/lookout/diff` directory.\n\n\
300
- This lookout on the design of the library also makes it easy to extend Lookout.\n\
301
- Lookout-rack was, for example, written in about four hours and about 5 of those\n\
302
- 240 minutes were spent on setting up the interface between the two.\n\n\
303
- ### Optimizing For Speed ###\n\n\
304
- The following paragraph is perhaps a bit personal, but might be interesting\n\
305
- nonetheless.\n\n\
306
- I\xE2\x80\x99ve always worried about speed. The original Expectations library used\n\
307
- `extend` a lot to add new behavior to objects. Expectations, for example, used\n\
308
- to hold the result of their execution (what we now term \xE2\x80\x9Cevaluation\xE2\x80\x9D) by being\n\
309
- extended by a module representing success, failure, or error. For the longest\n\
310
- time I used this same method, worrying about the increased performance cost\n\
311
- that creating new objects for results would incur. I finally came to a point\n\
312
- where I felt that the code was so simple and clean that rewriting this part of\n\
313
- the code for a benchmark wouldn\xE2\x80\x99t take more than perhaps ten minutes. Well,\n\
314
- ten minutes later I had my results and they confirmed that creating new objects\n\
315
- wasn\xE2\x80\x99t harming performance. I was very pleased.\n\n\
316
- ### Naming ###\n\n\
317
- I hate low lines (underscores). I try to avoid them in method names and I\n\
318
- always avoid them in file names. Since the current \xE2\x80\x9Cbest practice\xE2\x80\x9D in the Ruby\n\
319
- community is to put `BeginEndStorage` in a file called `begin_end_storage.rb`,\n\
320
- I only name constants using a single noun. This has had the added benefit that\n\
321
- classes seem to have acquired less behavior, as using a single noun doesn\xE2\x80\x99t\n\
322
- allow you to tack on additional behavior without questioning if it\xE2\x80\x99s really\n\
323
- appropriate to do so, given the rather limited range of interpretation for that\n\
324
- noun. It also seems to encourage the creation of value objects, as something\n\
325
- named `Range` feels a lot more like a value than `BeginEndStorage`. (To reach\n\
326
- object-oriented-programming Nirvana you must achieve complete value.)\n\n\n\
327
- ## Contributors ##\n\n\
328
- Contributors to the original expectations codebase are mentioned there. We\n\
329
- hope no one on that list feels left out of this list. Please [let us\n\
330
- know][Lookout issues] if you do.\n\n * Nikolai Weibull\n\n\
331
- [Lookout issues]: https://github.com/now/lookout/issues\n\n\n\
332
- ## License ##\n\n\
333
- You may use, copy, and redistribute this library under the same [terms][] as\n\
334
- Ruby itself.\n\n\
335
- [terms]: http://www.ruby-lang.org/en/LICENSE.txt\n"
23
+ prerelease: false
24
+ version_requirements: *14599272
25
+ description: ! " Lookout\n\n Lookout is a lightweight
26
+ unit testing framework. Tests (expectations) can be\n written as follows\n\n expect
27
+ 2 do\n 1 + 1\n end\n\n expect NoMethodError do\n Object.invalid_method_call\n
28
+ \ end\n\n Lookout is designed to encourage force, even unit testing best
29
+ practices\n such as\n\n• Setting up only one expectation per test\n• Not setting
30
+ expectations on non-public APIs\n• Test isolation\n\n This is done by\n\n• Only
31
+ allowing one expectation to be set per test\n• Providing no (additonal) way of
32
+ accessing private state\n• Providing no setup and teardown methods, nor a method
33
+ of providing test\n helpers\n\n Other important points are\n\n• A unified
34
+ syntax for setting up both state-based and behavior-based\n expectations\n• A
35
+ focus on code readability by providing no mechanism for describing an\n expectation
36
+ other than the code in the expectation itself\n\n The way Lookout works has been
37
+ heavily influenced by expectations¹, by\n {Jay Fields}². The code base was once
38
+ also heavily based on expectations¹,\n based at Subversion {revision 76}³. A lot
39
+ has happened since then and all of\n the work past that revision are due to {Nikolai
40
+ Weibull}⁴.\n\n¹ Get more information on the expectations library at http://expectations.rubyforge.org/\n²
41
+ Read Jay Fields’s blog at http://blog.jayfields.com/\n³ Review Lookout revision
42
+ 76 at https://github.com/now/lookout/commit/537bedf3e5b3eb4b31c066b3266f42964ac35ebe\n
43
+ Visit Nikolai Weibull’s home page at http://bitwi.se/\n\n§ Installation\n\n Install
44
+ Lookout with\n\n % gem install lookout\n\n\n§ Usage\n\n Lookout allows you
45
+ to set expectations on an object’s state or behavior.\n We’ll begin by looking
46
+ at state expectations and then take a look at\n expectations on behavior.\n\n
47
+ \ § Expectations on State\n\n An expectation can be made on the result of a
48
+ computation:\n\n expect 2 do\n 1 + 1\n end\n\n Most
49
+ objects, in fact, have their state expectations checked by invoking\n ‹#==›
50
+ on the expected value with the result as its argument.\n\n Checking that a
51
+ result is within a given range is also simple:\n\n expect 0.099..0.101 do\n
52
+ \ 0.4 - 0.3\n end\n\n Here, the more general ‹#===› is being
53
+ used on the ‹Range›.\n\n ‹Strings› of course match against ‹Strings›:\n\n expect
54
+ 'ab' do\n 'abc'[0..1]\n end\n\n but we can also match a ‹String›
55
+ against a ‹Regexp›:\n\n expect %r{a substring} do\n 'a string with
56
+ a substring'\n end\n\n (Note the use of ‹%r{…}› to avoid warnings that
57
+ will be generated when\n Ruby parses ‹expect /…/›.)\n\n Checking that
58
+ the result includes a certain module is done by expecting the\n ‹Module›.\n\n
59
+ \ expect Enumerable do\n []\n end\n\n This, due to the
60
+ nature of Ruby, of course also works for classes (as\n they are also modules):\n\n
61
+ \ expect String do\n 'a string'\n end\n\n This doesn’t
62
+ hinder us from expecting the actual ‹Module› itself:\n\n expect Enumerable
63
+ do\n Enumerable\n end\n\n As you may have figured out yourself,
64
+ this is accomplished by first\n trying ‹#==› and, if it returns ‹false›, then
65
+ trying ‹#===› on the\n expected ‹Module›. This is also true of ‹Ranges› and
66
+ ‹Regexps›.\n\n Truthfulness is expected with ‹true› and ‹false›:\n\n expect
67
+ true do\n 1\n end\n\n expect false do\n nil\n end\n\n
68
+ \ Results equaling ‹true› or ‹false› are slightly different:\n\n expect
69
+ TrueClass do\n true\n end\n\n expect FalseClass do\n false\n
70
+ \ end\n\n The rationale for this is that you should only care if the
71
+ result of a\n computation evaluates to a value that Ruby considers to be either
72
+ true or\n false, not the exact literals ‹true› or ‹false›.\n\n Expecting
73
+ output on an IO object is also common:\n\n expect output(\"abc\\ndef\\n\")
74
+ do |io|\n io.puts 'abc', 'def'\n end\n\n This can be used to
75
+ capture the output of a formatter that takes an\n output object as a parameter.\n\n
76
+ \ You should always be expecting errors from and in, but that’s a\n different
77
+ story your code:\n\n expect NoMethodError do\n Object.no_method\n
78
+ \ end\n\n Often, not only the type of the error, but its description,
79
+ is important\n to check:\n\n expect StandardError.new('message') do\n
80
+ \ raise StandardError.new('message')\n end\n\n As with ‹Strings›,
81
+ ‹Regexps› can be used to check the error description:\n\n expect StandardError.new(/mess/)
82
+ do\n raise StandardError.new('message')\n end\n\n (Note that
83
+ some of Ruby’s built-in error classes have slightly\n complicated behavior
84
+ and will not allow you to pass a ‹Regexp› as a\n parameter. ‹NameError› is
85
+ such a class. This may warrant further\n investigation into whether or not
86
+ this is a bug, but I’ll leave that up\n to the reader to decide.)\n\n Lookout
87
+ further provides a fluent way of setting up expectations on\n boolean results.
88
+ \ An object can “be”\n\n expect Class.new{ attr_accessor :running; }.new.to.be.running
89
+ do |process|\n process.running = true\n end\n\n or not be”\n\n
90
+ \ expect Class.new{ attr_accessor :running; }.new.not.to.be.running do |process|\n
91
+ \ process.running = false\n end\n\n or to “have”\n\n expect
92
+ Class.new{ attr_accessor :finished; }.new.to.have.finished do |process|\n process.finished
93
+ = true\n end\n\n or “not have”\n\n expect Class.new{ attr_accessor
94
+ :finished; }.new.not.to.have.finished do |process|\n process.finished =
95
+ false\n end\n\n On the same note\n\n expect nil.to.be.nil?\n\n
96
+ \ and\n\n expect Object.new.not.to.be.nil?\n\n As not every boolean
97
+ method “is” or “has” you can even\n\n expect nil.to.respond_to? :nil?\n\n
98
+ \ The rules here are that all ‹Objects› respond to ‹#to›. After ‹#to› you\n
99
+ \ may call\n\n • ‹#not›\n • ‹#be›\n • ‹#have›\n • Any method
100
+ whose name ends with ‹?›\n\n A call to ‹#not› must be followed by a call to
101
+ one of the three\n alternatives that follow it in the list. ‹#Be› and ‹#have›
102
+ must be\n followed by a call to a method.\n\n § Expectations on Behavior\n\n
103
+ \ We expect our objects to be on their best behavior. Lookout allows you\n
104
+ \ to make sure that they are.\n\n Mocks let use verify that a method is
105
+ called in the way that we expect it\n to be:\n\n expect mock.to.receive.dial('2125551212').twice
106
+ do |phone|\n phone.dial('2125551212')\n phone.dial('2125551212')\n
107
+ \ end\n\n Here, ‹#mock› creates a mock object, an object that doesn’t
108
+ respond to\n anything unless you tell it to. We tell it to expect to receive
109
+ a call\n to ‹#dail› with ‹'2125551212'› as its formal argument, and we expect
110
+ it\n to receive it twice. The mock object is then passed in to the block so\n
111
+ \ that the expectations placed upon it can be fulfilled.\n\n Sometimes
112
+ we only want to make sure that a method is called in the way\n that we expect
113
+ it to be, but we don’t care if any other methods are\n called on the object.
114
+ \ A stub object, created with ‹#stub›, expects any\n method and returns a stub
115
+ object that, again, expects any method, and\n thus fits the bill.\n\n expect
116
+ stub.to.receive.dial('2125551212').twice do |phone|\n phone.dial('2125551212')\n
117
+ \ phone.hangup\n phone.dial('2125551212')\n end\n\n We
118
+ can also use stubs without any expectations on them:\n\n expect 3 do\n s
119
+ = stub(:a => 1, :b => 2)\n s.a + s.b\n end\n\n and we can stub
120
+ out a specific method on an object:\n\n expect 'def' do\n a = 'abc'\n
121
+ \ stub(a).to_str{ 'def' }\n a.to_str\n end\n\n You
122
+ don’t have to use a mock object to verify that a method is called:\n\n expect
123
+ Object.to.receive.deal do\n Object.deal\n end\n\n As you have
124
+ figured out by now, the expected method call is set up by\n calling ‹#receive›
125
+ after ‹#to›. ‹#Receive› is followed by a call to the\n method to expect with
126
+ any expected arguments. The body of the mocked\n method can be given as the
127
+ block to the method. Finally, an expected\n invocation count may follow the
128
+ method. Let’s look at this formal\n specification in more detail.\n\n The
129
+ expected method arguments may be given in a variety of ways. Let’s\n introduce
130
+ them by giving some examples:\n\n expect mock.to.receive.a do |m|\n …\n
131
+ \ end\n\n Here, the method ‹#a› must be called with any number of arguments.
132
+ \ It\n may be called any number of times, but it must be called at least once.\n\n
133
+ \ If a method must receive exactly one argument, you can use ‹arg›:\n\n expect
134
+ mock.to.receive.a(arg) do |m|\n …\n end\n\n If a method must
135
+ receive a specific argument, you can use that argument:\n\n expect mock.to.receive.a(1..2)
136
+ do |m|\n …\n end\n\n The same matching rules apply for arguments
137
+ as they do for state\n expectations, so the previous example expects a call
138
+ to ‹#a› with 1, 2,\n or the Range 1..2 as an argument on ‹m›.\n\n If a
139
+ method must be invoked without any arguments you can use\n ‹without_arguments›:\n\n
140
+ \ expect mock.to.receive.a(without_arguments) do |m|\n …\n end\n\n
141
+ \ You can of course use both ‹arg› and actual arguments:\n\n expect mock.to.receive.a(arg,
142
+ 1, arg) do |m|\n …\n end\n\n The body of the mock method may
143
+ be given as the block. Here, calling\n ‹#a› on ‹m› will give the result ‹1›:\n\n
144
+ \ expect mock.to.receive.a{ 1 } do |m|\n …\n end\n\n If
145
+ no body has been given, the result will be a stub object.\n\n There is a caveat
146
+ here in that a block can’t yield in Ruby 1.8. To work\n around this deficiency
147
+ you have to use the ‹#yield› method:\n\n expect mock.to.receive.a.yield(1)
148
+ do |m|\n …\n end\n\n Any number of values to yield upon successive
149
+ calls may be given. The\n last value given will be used repeatedly when all
150
+ preceding values have\n been consumed. It’s also important to know that values
151
+ are splatted when\n they are yielded.\n\n To simulate an ‹#each›-like
152
+ method you can use ‹#each›. The following\n horrible example should give you
153
+ an idea of how to use it.\n\n expect Object.new.to.receive.each.each(1, 2,
154
+ 3) do |o|\n class << o\n include Enumerable\n end\n
155
+ \ o.inject{ |i, a| i + a }\n end\n\n Invocation count expectations
156
+ can also be set if the default expectation\n of “at least once” isn’t good
157
+ enough. The following expectations are\n possible\n\n • ‹#at_most_once›\n
158
+ \ • ‹#once›\n • ‹#at_least_once›\n • ‹#twice›\n\n And, for a
159
+ given ‹N›,\n\n • ‹#at_most(N)›\n • ‹#exactly(N)›\n • ‹#at_least(N)›\n\n
160
+ \ Method stubs are another useful thing to have in a unit testing\n framework.
161
+ \ Sometimes you need to override a method that does something a\n test shouldn’t
162
+ do, like access and alter bank accounts. We can override\n – stub out – a
163
+ method by using the ‹#stub› method. Let’s assume that we\n have an ‹Account›
164
+ class that has two methods, ‹#slips› and ‹#total›.\n ‹#Slips› retrieves the
165
+ bank slips that keep track of your deposits to the\n ‹Account› from a database.
166
+ \ ‹#Total› sums the ‹#slips›. In the following\n test we want to make sure
167
+ that ‹#total› does what it should do without\n accessing the database. We
168
+ therefore stub out ‹#slips› and make it\n return something that we can easily
169
+ control.\n\n expect 6 do |m|\n account = Account.new\n stub(account).slips{
170
+ [1, 2, 3] }\n account.total\n end\n\n As with mock methods,
171
+ if no body is given, the result will be a stub\n object.\n\n To make it
172
+ easy to create objects with a set of stubbed methods there’s\n also a convenience
173
+ method:\n\n expect 3 do\n s = stub(:a => 1, :b => 2)\n s.a
174
+ + s.b\n end\n\n Please note that this makes it impossible to stub a
175
+ method on a Hash, but\n you shouldn’t be doing that anyway. In fact, you should
176
+ never mock or\n stub methods on value objects.\n\n§ Integration\n\n Lookout
177
+ can be used from Rake¹. Simply include the following code in\n your ‹Rakefile›:\n\n
178
+ \ require 'lookout/rake/tasks'\n\n Lookout::Rake::Tasks::Test.new\n\n If
179
+ the ‹:default› task hasn’t been defined it will be set to depend on the\n ‹:test›
180
+ task.\n\n As an added bonus you can use Lookout’s own gem² tasks:\n\n Lookout::Rake::Tasks::Gem.new\n\n
181
+ \ This provides tasks to ‹build›, ‹check›, ‹install›, and ‹push› your gem.\n\n
182
+ \ To use Lookout together with Vim³, place ‹contrib/rakelookout.vim› in\n ‹~/.vim/compiler›
183
+ and add\n\n compiler rakelookout\n\n to ‹~/.vim/after/ftplugin/ruby.vim›.
184
+ \ Executing ‹:make› from inside Vim\n will now run your tests and an errors and
185
+ failures can be visited with\n ‹:cnext›. Execute ‹:help quickfix› for additional
186
+ information.\n\n Another useful addition to your ‹~/.vim/after/ftplugin/ruby.vim›
187
+ file may\n be\n\n nnoremap <buffer> <silent> <Leader>M <Esc>:call <SID>run_test()<CR>\n
188
+ \ let b:undo_ftplugin .= ' | nunmap <buffer> <Leader>M'\n\n function! s:run_test()\n
189
+ \ let test = expand('%')\n let line = 'LINE=' . line('.')\n if
190
+ test =~ '^lib/'\n let test = substitute(test, '^lib/', 'test/', '')\n let
191
+ line = \"\"\n endif\n execute 'make' 'TEST=' . shellescape(test) line\n
192
+ \ endfunction\n\n Now, pressing ‹<Leader>M› will either run all tests for
193
+ a given class, if\n the implementation file is active, or run the test at or
194
+ just before the\n cursor, if the test file is active. This is useful if you’re
195
+ currently\n receiving a lot of errors and/or failures and want to focus on those\n
196
+ \ associated with a specific class or on a specific test.\n\n¹ Read more about
197
+ Rake at http://rake.rubyforge.org/\n² Get information on RubyGems at http://rubygems.org/\n³
198
+ Find out more about Vim at http://www.vim.org/\n\ Interface Design\n\n The
199
+ default output of Lookout can Spartanly be described as Spartan. If no\n errors
200
+ or failures occur, no output is generated. This is unconventional,\n as unit
201
+ testing frameworks tend to dump a lot of information on the user,\n concerning
202
+ things such as progress, test count summaries, and flamboyantly\n colored text
203
+ telling you that your tests passed. None of this output is\n needed. Your tests
204
+ should run fast enough to not require progress reports.\n The lack of output
205
+ provides you with the same amount of information as\n reporting success. Test
206
+ count summaries are only useful if you’re worried\n that your tests aren’t being
207
+ run, but if you worry about that, then\n providing such output doesn’t really
208
+ help. Testing your tests requires\n something beyond reporting some arbitrary
209
+ count that you would have to\n verify by hand anyway.\n\n When errors or failures
210
+ do occur, however, the relevant information is\n output in a format that can
211
+ easily be parsed by an ‹'errorformat'› for Vim\n or with {Compilation Mode}¹
212
+ for Emacs². Diffs are generated for Strings,\n Arrays, Hashes, and I/O.\n\n¹
213
+ Read up on Compilation mode for Emacs at http://www.emacswiki.org/emacs/CompilationMode\n²
214
+ Visit The GNU Foundation’s Emacs’ software page at http://www.gnu.org/software/emacs/\n\
215
+ External Design\n\n Let’s now look at some of the points made in the introduction
216
+ in greater\n detail.\n\n Lookout only allows you to set one expectation per
217
+ test. If you’re testing\n behavior with a mock, then only one method-invocation
218
+ expectation can be\n set. If you’re testing state, then only one result can
219
+ be verified. It\n may seem like this would cause unnecessary duplication between
220
+ tests.\n While this is certainly a possibility, when you actually begin to try
221
+ to\n avoid such duplication you find that you often do so by improving your\n
222
+ \ interfaces. This kind of restriction tends to encourage the use of value\n
223
+ \ objects, which are easy to test, and more focused objects, which require\n simpler
224
+ tests, as they have less behavior to test, per method. By keeping\n your interfaces
225
+ focused you’re also keeping your tests focused.\n\n Keeping your tests focused
226
+ improves, in itself, test isolation, but let’s\n look at something that hinders
227
+ it: setup and teardown methods. Most unit\n testing frameworks encourage test
228
+ fragmentation by providing setup and\n teardown methods.\n\n Setup methods
229
+ create objects and, perhaps, just their behavior for a set of\n tests. This
230
+ means that you have to look in two places to figure out what’s\n being done in
231
+ a test. This may work fine for few methods with simple\n set-ups, but makes
232
+ things complicated when the number of tests increases\n and the set-up is complex.
233
+ \ Often, each test further adjusts the previously\n set-up object before performing
234
+ any verifications, further complicating the\n process of figuring out what state
235
+ an object has in a given test.\n\n Teardown methods clean up after tests, perhaps
236
+ by removing records from a\n database or deleting files from the file-system.
237
+ \ \n\n The duplication that setup methods and teardown methods hope to remove
238
+ is\n better avoided by improving your interfaces. This can be done by providing\n
239
+ \ better set-up methods for your objects and using idioms such as {Resource\n
240
+ \ Acquisition Is Initialization}¹ for guaranteed clean-up, test or no test.\n\n
241
+ \ By not using setup and teardown methods we keep everything pertinent to a\n
242
+ \ test in the test itself, thus improving test isolation. (You also won’t\n {slow
243
+ down your tests}² by keeping unnecessary state.)\n\n Most unit test frameworks
244
+ also allow you to create arbitrary test helper\n methods. Lookout doesn’t. The
245
+ same rationale as that that has been\n crystallized in the preceding paragraphs
246
+ applies. If you need helpers\n you’re interface isn’t good enough. It really
247
+ is as simple as that.\n\n To clarify: there’s nothing inherently wrong with test
248
+ helper methods, but\n they should be general enough that they reside in their
249
+ own library. The\n support for mocks in Lookout is provided through a set of
250
+ test helper\n methods that make it easier to create mocks than it would have
251
+ been without\n them. Lookout-rack³ is another example of a library providing
252
+ test helper\n methods (well, one of method, actually) that are very useful in
253
+ testing web\n applications that use Rack⁴.\n\n A final point at which some
254
+ unit test frameworks try to fragment tests\n further is documentation. These
255
+ frameworks provide ways of describing the\n whats and hows of what’s being tested,
256
+ the rationale being that this will\n provide documentation of both the test and
257
+ the code being tested.\n Describing how a stack data structure is meant to work
258
+ is a common example.\n A stack is, however, a rather simple data structure, so
259
+ such a description\n provides little, if any, additional information that can’t
260
+ be extracted\n from the implementation and its tests themselves. The implementation
261
+ and\n its tests is, in fact, its own best documentation. Taking the points made\n
262
+ \ in the previous paragraphs into account, we should already have simple,\n self-describing,
263
+ interfaces that have easily understood tests associated\n with them. Rationales
264
+ for the use of a given data structure or\n system-design design documentation
265
+ is better suited in separate\n documentation focused at describing exactly those
266
+ issues.\n\n¹ Read the Wikipedia entry for Resource Acquisition Is Initialization
267
+ at\n http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization\n² Read
268
+ how 37signals had problems with slow Test::Unit tests at\n http://37signals.com/svn/posts/2742-the-road-to-faster-tests/\n³
269
+ Visit the Lookout-rack GitHub project page at\n http://github.com/now/lookout-rack/\n⁴
270
+ Visit the Rack Rubyforge project page at\n http://rack.rubyforge.org/\n\n§ Internal
271
+ Design\n\n The internal design of Lookout has had a couple of goals.\n\n • As
272
+ few external dependencies as possible\n • As few internal dependencies as possible\n
273
+ \ • Internal extensibility provides external extensibility\n • As fast load
274
+ times as possible\n • As high a ratio of value objects to mutable objects as
275
+ possible\n • Each object must have a simple, obvious name\n • Use mix-ins,
276
+ not inheritance for shared behavior\n • As few responsibilities per object as
277
+ possible\n • Optimizing for speed can only be done when you have all the facts\n\n§
278
+ External Dependencies\n\n Lookout used to depend on Mocha for mocks and stubs.
279
+ \ While benchmarking I\n noticed that a method in Mocha was taking up more than
280
+ 300 percent of the\n runtime. It turned out that Mocha’s method for cleaning
281
+ up back-traces\n generated when a mock failed was doing something incredibly
282
+ stupid:\n\n backtrace.reject{ |l| Regexp.new(@lib).match(File.expand_path(l))
283
+ }\n\n Here ‹@lib› is a ‹String› containing the path to the lib subdirectory in\n
284
+ \ the Mocha installation directory. I reported it, provided a patch five\n days
285
+ later, then waited. Nothing happened. {254 days later}¹, according\n to {Wolfram
286
+ Alpha}², half of my patch was, apparently – I say “apparently”,\n as I received
287
+ no notification applied. By that time I had replaced the\n whole mocking-and-stubbing
288
+ subsystem and dropped the dependency.\n\n Many Ruby developers claim that Ruby
289
+ and its gems are too fast-moving for\n normal package-managing systems to keep
290
+ up. This is testament to the fact\n that this isn’t the case and that the real
291
+ problem is instead related to\n sloppy practices.\n\n Please note that I don’t
292
+ want to single out the Mocha library nor its\n developers. I only want to provide
293
+ an example where relying on external\n dependencies can be “considered harmful”.\n\n¹
294
+ See the Wolfram Alpha calculation at http://www.wolframalpha.com/input/?i=days+between+march+17%2C+2010+and+november+26%2C+2010\n²
295
+ Check out the Wolfram Alpha computational knowledge engine at http://www.wolframalpha.com/\n\n§
296
+ Internal Dependencies\n\n Lookout has been designed so as to keep each subsystem
297
+ independent of any\n other. The diff subsystem is, for example, completely decoupled
298
+ from any\n other part of the system as a whole and could be moved into its own
299
+ library\n at a time where that would be of interest to anyone. What’s perhaps
300
+ more\n interesting is that the diff subsystem is itself very modular. The data\n
301
+ \ passes through a set of filters that depends on what kind of diff has been\n
302
+ \ requested, each filter yielding modified data as it receives it. If you\n want
303
+ to read some rather functional Ruby I can highly recommend looking at\n the code
304
+ in the ‹lib/lookout/diff› directory.\n\n This lookout on the design of the library
305
+ also makes it easy to extend\n Lookout. Lookout-rack was, for example, written
306
+ in about four hours and\n about 5 of those 240 minutes were spent on setting
307
+ up the interface between\n the two.\n\n§ Optimizing For Speed\n\n The following
308
+ paragraph is perhaps a bit personal, but might be interesting\n nonetheless.\n\n
309
+ \ I’ve always worried about speed. The original Expectations library used\n ‹extend›
310
+ a lot to add new behavior to objects. Expectations, for example,\n used to hold
311
+ the result of their execution (what we now term “evaluation”)\n by being extended
312
+ by a module representing success, failure, or error. For\n the longest time
313
+ I used this same method, worrying about the increased\n performance cost that
314
+ creating new objects for results would incur. I\n finally came to a point where
315
+ I felt that the code was so simple and clean\n that rewriting this part of the
316
+ code for a benchmark wouldn’t take more\n than perhaps ten minutes. Well, ten
317
+ minutes later I had my results and\n they confirmed that creating new objects
318
+ wasn’t harming performance. I was\n very pleased.\n\n§ Naming\n\n I hate
319
+ low lines (underscores). I try to avoid them in method names and I\n always
320
+ avoid them in file names. Since the current “best practice” in the\n Ruby community
321
+ is to put ‹BeginEndStorage› in a file called\n ‹begin_end_storage.rb›, I only
322
+ name constants using a single noun. This\n has had the added benefit that classes
323
+ seem to have acquired less behavior,\n as using a single noun doesn’t allow you
324
+ to tack on additional behavior\n without questioning if it’s really appropriate
325
+ to do so, given the rather\n limited range of interpretation for that noun. It
326
+ also seems to encourage\n the creation of value objects, as something named ‹Range›
327
+ feels a lot more\n like a value than ‹BeginEndStorage›. (To reach object-oriented-programming\n
328
+ \ Nirvana you must achieve complete value.)\n\n\n§ Contributors\n\n Contributors
329
+ to the original expectations codebase are mentioned there. We\n hope no one
330
+ on that list feels left out of this list. Please\n {let us know}¹ if you do.\n\n
331
+ \ • Nikolai Weibull\n\n¹ Add an issue to the Lookout issue tracker at https://github.com/now/lookout/issues\n\n\n§
332
+ License\n\n You may use, copy, and redistribute this library under the same terms¹\n
333
+ \ as Ruby itself.\n\n¹ Read the Ruby licensing terms at http://www.ruby-lang.org/en/LICENSE.txt\n"
336
334
  email: now@bitwi.se
337
335
  executables: []
338
-
339
336
  extensions: []
340
-
341
337
  extra_rdoc_files: []
342
-
343
- files:
344
- - lib/lookout/diff.rb
345
- - lib/lookout/diff/algorithms.rb
346
- - lib/lookout/diff/algorithms/difflib.rb
347
- - lib/lookout/diff/algorithms/difflib/position.rb
338
+ files:
339
+ - lib/lookout/aphonic.rb
348
340
  - lib/lookout/diff/algorithms/difflib/position/to.rb
349
- - lib/lookout/diff/formats.rb
341
+ - lib/lookout/diff/algorithms/difflib/position.rb
342
+ - lib/lookout/diff/algorithms/difflib.rb
343
+ - lib/lookout/diff/algorithms.rb
350
344
  - lib/lookout/diff/formats/hash.rb
351
345
  - lib/lookout/diff/formats/inline.rb
352
346
  - lib/lookout/diff/formats/unified.rb
347
+ - lib/lookout/diff/formats.rb
353
348
  - lib/lookout/diff/group.rb
354
349
  - lib/lookout/diff/groups.rb
355
350
  - lib/lookout/diff/match.rb
356
351
  - lib/lookout/diff/operation.rb
357
- - lib/lookout/diff/operations.rb
358
352
  - lib/lookout/diff/operations/delete.rb
359
353
  - lib/lookout/diff/operations/equal.rb
360
354
  - lib/lookout/diff/operations/insert.rb
361
355
  - lib/lookout/diff/operations/replace.rb
356
+ - lib/lookout/diff/operations.rb
362
357
  - lib/lookout/diff/range.rb
358
+ - lib/lookout/diff.rb
359
+ - lib/lookout/equalities/array.rb
360
+ - lib/lookout/equalities/boolean.rb
361
+ - lib/lookout/equalities/hash.rb
362
+ - lib/lookout/equalities/include.rb
363
+ - lib/lookout/equalities/object.rb
364
+ - lib/lookout/equalities/output.rb
365
+ - lib/lookout/equalities/standarderror.rb
366
+ - lib/lookout/equalities/string.rb
367
+ - lib/lookout/equalities/warning.rb
368
+ - lib/lookout/equalities.rb
369
+ - lib/lookout/equality.rb
370
+ - lib/lookout/expectation.rb
363
371
  - lib/lookout/expectations/behavior.rb
372
+ - lib/lookout/expectations/line.rb
364
373
  - lib/lookout/expectations/state/warning.rb
365
374
  - lib/lookout/expectations/state.rb
366
- - lib/lookout/mock/method.rb
367
- - lib/lookout/mock/method/arguments.rb
375
+ - lib/lookout/expectations.rb
368
376
  - lib/lookout/mock/method/arguments/any.rb
369
377
  - lib/lookout/mock/method/arguments/anything.rb
370
378
  - lib/lookout/mock/method/arguments/list.rb
371
379
  - lib/lookout/mock/method/arguments/none.rb
372
380
  - lib/lookout/mock/method/arguments/one.rb
373
- - lib/lookout/mock/method/calls.rb
381
+ - lib/lookout/mock/method/arguments.rb
374
382
  - lib/lookout/mock/method/calls/class.rb
375
383
  - lib/lookout/mock/method/calls/exactly.rb
376
384
  - lib/lookout/mock/method/calls/instance.rb
377
385
  - lib/lookout/mock/method/calls/lower.rb
378
386
  - lib/lookout/mock/method/calls/upper.rb
387
+ - lib/lookout/mock/method/calls.rb
388
+ - lib/lookout/mock/method.rb
379
389
  - lib/lookout/mock/methods.rb
380
390
  - lib/lookout/mock/object.rb
391
+ - lib/lookout/mock.rb
381
392
  - lib/lookout/object.rb
382
393
  - lib/lookout/output.rb
383
- - lib/lookout/rake/tasks/test/loader.rb
394
+ - lib/lookout/rake/tasks/gem.rb
384
395
  - lib/lookout/rake/tasks/tags.rb
396
+ - lib/lookout/rake/tasks/test/loader.rb
385
397
  - lib/lookout/rake/tasks/test.rb
386
- - lib/lookout/rake/tasks/gem.rb
387
398
  - lib/lookout/rake/tasks.rb
388
399
  - lib/lookout/recorder/not.rb
389
400
  - lib/lookout/recorder/tape.rb
401
+ - lib/lookout/recorder.rb
390
402
  - lib/lookout/recorders/reception.rb
391
403
  - lib/lookout/recorders/state.rb
392
- - lib/lookout/results/failures.rb
393
- - lib/lookout/results/failures/behavior.rb
394
- - lib/lookout/results/failures/state.rb
395
- - lib/lookout/results/error/exception.rb
404
+ - lib/lookout/recorders.rb
405
+ - lib/lookout/result.rb
396
406
  - lib/lookout/results/error/exception/backtrace.rb
397
- - lib/lookout/results/unsuccessful.rb
407
+ - lib/lookout/results/error/exception.rb
398
408
  - lib/lookout/results/error.rb
399
- - lib/lookout/results/fulfilled.rb
400
- - lib/lookout/results/instance.rb
401
409
  - lib/lookout/results/failure.rb
402
- - lib/lookout/runners.rb
410
+ - lib/lookout/results/failures/behavior.rb
411
+ - lib/lookout/results/failures/state.rb
412
+ - lib/lookout/results/failures.rb
413
+ - lib/lookout/results/fulfilled.rb
414
+ - lib/lookout/results/unsuccessful.rb
415
+ - lib/lookout/results.rb
403
416
  - lib/lookout/runners/console.rb
417
+ - lib/lookout/runners/trackers/failure.rb
418
+ - lib/lookout/runners/trackers.rb
419
+ - lib/lookout/runners.rb
404
420
  - lib/lookout/stub/method.rb
405
421
  - lib/lookout/stub/methods.rb
406
422
  - lib/lookout/stub/object.rb
407
- - lib/lookout/ui.rb
408
- - lib/lookout/ui/silent.rb
423
+ - lib/lookout/stub.rb
409
424
  - lib/lookout/ui/console.rb
410
- - lib/lookout/xml.rb
411
- - lib/lookout/aphonic.rb
412
- - lib/lookout/recorder.rb
413
- - lib/lookout/recorders.rb
414
- - lib/lookout/expectation.rb
425
+ - lib/lookout/ui/silent.rb
426
+ - lib/lookout/ui.rb
415
427
  - lib/lookout/version.rb
416
- - lib/lookout/expectations.rb
417
- - lib/lookout/equalities/object.rb
418
- - lib/lookout/equalities/include.rb
419
- - lib/lookout/equalities/boolean.rb
420
- - lib/lookout/equalities/string.rb
421
- - lib/lookout/equalities/array.rb
422
- - lib/lookout/equalities/hash.rb
423
- - lib/lookout/equalities/standarderror.rb
424
- - lib/lookout/equalities/output.rb
425
- - lib/lookout/equalities/warning.rb
426
- - lib/lookout/equality.rb
427
428
  - lib/lookout/warning.rb
428
- - lib/lookout/mock.rb
429
- - lib/lookout/stub.rb
430
- - lib/lookout/results.rb
431
- - lib/lookout/result.rb
432
- - lib/lookout/equalities.rb
429
+ - lib/lookout/xml.rb
433
430
  - lib/lookout.rb
434
- - test/unit/lookout/diff.rb
435
- - test/unit/lookout/diff/algorithms/difflib.rb
436
- - test/unit/lookout/diff/algorithms/difflib/position.rb
431
+ - test/unit/examples.rb
437
432
  - test/unit/lookout/diff/algorithms/difflib/position/to.rb
433
+ - test/unit/lookout/diff/algorithms/difflib/position.rb
434
+ - test/unit/lookout/diff/algorithms/difflib.rb
438
435
  - test/unit/lookout/diff/formats/inline.rb
439
436
  - test/unit/lookout/diff/formats/unified.rb
440
437
  - test/unit/lookout/diff/group.rb
441
438
  - test/unit/lookout/diff/groups.rb
442
439
  - test/unit/lookout/diff/match.rb
443
- - test/unit/lookout/diff/operations.rb
444
440
  - test/unit/lookout/diff/operations/delete.rb
445
441
  - test/unit/lookout/diff/operations/equal.rb
446
442
  - test/unit/lookout/diff/operations/insert.rb
447
443
  - test/unit/lookout/diff/operations/replace.rb
444
+ - test/unit/lookout/diff/operations.rb
448
445
  - test/unit/lookout/diff/range.rb
446
+ - test/unit/lookout/diff.rb
449
447
  - test/unit/lookout/equality.rb
450
448
  - test/unit/lookout/expectation.rb
451
- - test/unit/lookout/expectations/state.rb
452
449
  - test/unit/lookout/expectations/behavior.rb
453
- - test/unit/lookout/mock/method.rb
454
- - test/unit/lookout/mock/method/arguments.rb
450
+ - test/unit/lookout/expectations/line.rb
451
+ - test/unit/lookout/expectations/state.rb
452
+ - test/unit/lookout/expectations.rb
455
453
  - test/unit/lookout/mock/method/arguments/any.rb
454
+ - test/unit/lookout/mock/method/arguments.rb
455
+ - test/unit/lookout/mock/method.rb
456
456
  - test/unit/lookout/recorder.rb
457
+ - test/unit/lookout/results/error/exception/backtrace.rb
458
+ - test/unit/lookout/results/error.rb
457
459
  - test/unit/lookout/results/failures/behavior.rb
458
460
  - test/unit/lookout/results/failures/state.rb
459
- - test/unit/lookout/results/unsuccessful.rb
460
- - test/unit/lookout/results/error.rb
461
461
  - test/unit/lookout/results/fulfilled.rb
462
+ - test/unit/lookout/results/unsuccessful.rb
463
+ - test/unit/lookout/results.rb
462
464
  - test/unit/lookout/runners/console.rb
465
+ - test/unit/lookout/runners/trackers/failure.rb
463
466
  - test/unit/lookout/stub/method.rb
464
467
  - test/unit/lookout/stub/methods.rb
465
- - test/unit/lookout/ui/formatters/exception.rb
466
- - test/unit/lookout/ui/formatters/exception/backtrace.rb
468
+ - test/unit/lookout/ui/console.rb
467
469
  - test/unit/lookout/xml.rb
468
- - test/unit/lookout/results.rb
469
- - test/unit/lookout/expectations.rb
470
- - test/unit/examples.rb
471
470
  - test/unit/lookout.rb
472
471
  - README
473
472
  - Rakefile
474
- has_rdoc: true
475
473
  homepage: http://github.com/now/lookout
476
474
  licenses: []
477
-
475
+ metadata: {}
478
476
  post_install_message:
479
477
  rdoc_options: []
480
-
481
- require_paths:
478
+ require_paths:
482
479
  - lib
483
- required_ruby_version: !ruby/object:Gem::Requirement
480
+ required_ruby_version: !ruby/object:Gem::Requirement
484
481
  none: false
485
- requirements:
486
- - - ">="
487
- - !ruby/object:Gem::Version
488
- hash: 3
489
- segments:
490
- - 0
491
- version: "0"
492
- required_rubygems_version: !ruby/object:Gem::Requirement
482
+ requirements:
483
+ - - ! '>='
484
+ - !ruby/object:Gem::Version
485
+ version: '0'
486
+ required_rubygems_version: !ruby/object:Gem::Requirement
493
487
  none: false
494
- requirements:
495
- - - ">="
496
- - !ruby/object:Gem::Version
497
- hash: 3
498
- segments:
499
- - 0
500
- version: "0"
488
+ requirements:
489
+ - - ! '>='
490
+ - !ruby/object:Gem::Version
491
+ version: '0'
501
492
  requirements: []
502
-
503
493
  rubyforge_project:
504
- rubygems_version: 1.3.7
494
+ rubygems_version: 1.8.10
505
495
  signing_key:
506
- specification_version: 3
496
+ specification_version: 4
507
497
  summary: Lookout is a lightweight unit testing framework.
508
498
  test_files: []
509
-