lookout 2.3.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README +351 -181
- data/Rakefile +20 -5
- data/lib/lookout-3.0.rb +138 -0
- data/lib/lookout-3.0/actual.rb +30 -0
- data/lib/lookout-3.0/actual/method.rb +31 -0
- data/lib/lookout-3.0/actual/not.rb +13 -0
- data/lib/lookout-3.0/actual/not/method.rb +10 -0
- data/lib/lookout-3.0/aphonic.rb +44 -0
- data/lib/lookout-3.0/diff.rb +29 -0
- data/lib/{lookout → lookout-3.0}/diff/algorithms.rb +1 -1
- data/lib/lookout-3.0/diff/algorithms/difflib.rb +62 -0
- data/lib/lookout-3.0/diff/algorithms/difflib/position.rb +63 -0
- data/lib/{lookout/diff/algorithms/difflib/position/to.rb → lookout-3.0/diff/algorithms/difflib/position/new.rb} +8 -17
- data/lib/lookout-3.0/diff/formats.rb +5 -0
- data/lib/lookout-3.0/diff/formats/inline.rb +43 -0
- data/lib/lookout-3.0/diff/formats/set.rb +48 -0
- data/lib/lookout-3.0/diff/formats/unified.rb +56 -0
- data/lib/lookout-3.0/diff/group.rb +57 -0
- data/lib/lookout-3.0/diff/groups.rb +47 -0
- data/lib/lookout-3.0/diff/match.rb +31 -0
- data/lib/lookout-3.0/diff/operation.rb +41 -0
- data/lib/lookout-3.0/diff/operations.rb +35 -0
- data/lib/lookout-3.0/diff/operations/copy.rb +25 -0
- data/lib/lookout-3.0/diff/operations/delete.rb +5 -0
- data/lib/lookout-3.0/diff/operations/insert.rb +5 -0
- data/lib/lookout-3.0/diff/operations/replace.rb +6 -0
- data/lib/lookout-3.0/diff/slice.rb +97 -0
- data/lib/lookout-3.0/difference.rb +10 -0
- data/lib/lookout-3.0/difference/array.rb +22 -0
- data/lib/lookout-3.0/difference/exception.rb +40 -0
- data/lib/lookout-3.0/difference/hash.rb +31 -0
- data/lib/lookout-3.0/difference/lookout.rb +5 -0
- data/lib/lookout-3.0/difference/lookout/actual.rb +6 -0
- data/lib/lookout-3.0/difference/lookout/actual/method.rb +13 -0
- data/lib/lookout-3.0/difference/lookout/actual/not.rb +6 -0
- data/lib/lookout-3.0/difference/lookout/actual/not/method.rb +9 -0
- data/lib/lookout-3.0/difference/lookout/output.rb +8 -0
- data/lib/lookout-3.0/difference/lookout/reception.rb +21 -0
- data/lib/lookout-3.0/difference/lookout/warning.rb +9 -0
- data/lib/lookout-3.0/difference/module.rb +12 -0
- data/lib/lookout-3.0/difference/object.rb +73 -0
- data/lib/lookout-3.0/difference/range.rb +12 -0
- data/lib/lookout-3.0/difference/regexp.rb +12 -0
- data/lib/lookout-3.0/difference/string.rb +21 -0
- data/lib/lookout-3.0/difference/symbol.rb +21 -0
- data/lib/lookout-3.0/encode.rb +20 -0
- data/lib/lookout-3.0/exception.rb +79 -0
- data/lib/lookout-3.0/exception/backtrace.rb +65 -0
- data/lib/lookout-3.0/exception/unknown.rb +25 -0
- data/lib/lookout-3.0/expect.rb +32 -0
- data/lib/lookout-3.0/expect/classes.rb +6 -0
- data/lib/lookout-3.0/expect/classes/exception.rb +27 -0
- data/lib/lookout-3.0/expect/exception.rb +30 -0
- data/lib/lookout-3.0/expect/object.rb +54 -0
- data/lib/lookout-3.0/expect/object/context.rb +149 -0
- data/lib/lookout-3.0/expectations.rb +69 -0
- data/lib/lookout-3.0/expectations/context.rb +52 -0
- data/lib/lookout-3.0/expected.rb +10 -0
- data/lib/lookout-3.0/expected/array.rb +16 -0
- data/lib/lookout-3.0/expected/classes.rb +5 -0
- data/lib/lookout-3.0/expected/classes/exception.rb +14 -0
- data/lib/lookout-3.0/expected/exception.rb +46 -0
- data/lib/lookout-3.0/expected/falseclass.rb +9 -0
- data/lib/lookout-3.0/expected/hash.rb +14 -0
- data/lib/lookout-3.0/expected/lookout.rb +5 -0
- data/lib/lookout-3.0/expected/lookout/actual.rb +5 -0
- data/lib/lookout-3.0/expected/lookout/actual/method.rb +13 -0
- data/lib/lookout-3.0/expected/lookout/actual/not.rb +6 -0
- data/lib/lookout-3.0/expected/lookout/actual/not/method.rb +13 -0
- data/lib/lookout-3.0/expected/lookout/output.rb +26 -0
- data/lib/lookout-3.0/expected/lookout/reception.rb +24 -0
- data/lib/lookout-3.0/expected/lookout/warning.rb +29 -0
- data/lib/lookout-3.0/expected/module.rb +12 -0
- data/lib/lookout-3.0/expected/object.rb +30 -0
- data/lib/lookout-3.0/expected/range.rb +12 -0
- data/lib/lookout-3.0/expected/regexp.rb +12 -0
- data/lib/lookout-3.0/expected/string.rb +11 -0
- data/lib/lookout-3.0/expected/symbol.rb +21 -0
- data/lib/lookout-3.0/expected/trueclass.rb +9 -0
- data/lib/lookout-3.0/inspect.rb +45 -0
- data/lib/lookout-3.0/interfaces.rb +5 -0
- data/lib/lookout-3.0/interfaces/commandline.rb +109 -0
- data/lib/lookout-3.0/literal.rb +18 -0
- data/lib/lookout-3.0/mock.rb +24 -0
- data/lib/lookout-3.0/object.rb +6 -0
- data/lib/lookout-3.0/object/not.rb +16 -0
- data/lib/lookout-3.0/object/not/receive.rb +18 -0
- data/lib/lookout-3.0/object/to.rb +12 -0
- data/lib/lookout-3.0/object/to/receive.rb +18 -0
- data/lib/lookout-3.0/output.rb +20 -0
- data/lib/lookout-3.0/plugins.rb +7 -0
- data/lib/lookout-3.0/reception.rb +128 -0
- data/lib/lookout-3.0/reception/arguments.rb +20 -0
- data/lib/lookout-3.0/reception/arguments/any.rb +16 -0
- data/lib/lookout-3.0/reception/arguments/error.rb +5 -0
- data/lib/lookout-3.0/reception/arguments/list.rb +17 -0
- data/lib/lookout-3.0/reception/arguments/none.rb +6 -0
- data/lib/lookout-3.0/reception/error.rb +24 -0
- data/lib/lookout-3.0/result.rb +16 -0
- data/lib/lookout-3.0/results.rb +5 -0
- data/lib/lookout-3.0/results/error.rb +18 -0
- data/lib/lookout-3.0/results/failure.rb +15 -0
- data/lib/lookout-3.0/results/success.rb +7 -0
- data/lib/lookout-3.0/stub.rb +55 -0
- data/lib/lookout-3.0/version.rb +133 -0
- data/lib/lookout-3.0/warning.rb +40 -0
- data/test/unit/examples.rb +208 -83
- data/test/unit/{lookout.rb → lookout-3.0.rb} +0 -0
- data/test/unit/lookout-3.0/actual.rb +13 -0
- data/test/unit/lookout-3.0/actual/method.rb +31 -0
- data/test/unit/lookout-3.0/actual/not.rb +15 -0
- data/test/unit/lookout-3.0/actual/not/method.rb +7 -0
- data/test/unit/lookout-3.0/aphonic.rb +31 -0
- data/test/unit/{lookout → lookout-3.0}/diff.rb +0 -0
- data/test/unit/{lookout/diff/group.rb → lookout-3.0/diff/algorithms.rb} +0 -0
- data/test/unit/lookout-3.0/diff/algorithms/difflib.rb +56 -0
- data/test/unit/lookout-3.0/diff/algorithms/difflib/position.rb +92 -0
- data/test/unit/{lookout/diff/algorithms/difflib/position/to.rb → lookout-3.0/diff/algorithms/difflib/position/new.rb} +1 -2
- data/test/unit/{lookout/results.rb → lookout-3.0/diff/formats.rb} +0 -0
- data/test/unit/{lookout → lookout-3.0}/diff/formats/inline.rb +0 -0
- data/test/unit/lookout-3.0/diff/formats/set.rb +26 -0
- data/test/unit/{lookout → lookout-3.0}/diff/formats/unified.rb +0 -0
- data/test/unit/{lookout/results/error.rb → lookout-3.0/diff/group.rb} +0 -0
- data/test/unit/lookout-3.0/diff/groups.rb +102 -0
- data/test/unit/{lookout → lookout-3.0}/diff/match.rb +0 -0
- data/test/unit/lookout-3.0/diff/operation.rb +17 -0
- data/test/unit/lookout-3.0/diff/operations.rb +22 -0
- data/test/unit/lookout-3.0/diff/operations/copy.rb +50 -0
- data/test/unit/lookout-3.0/diff/operations/delete.rb +45 -0
- data/test/unit/lookout-3.0/diff/operations/insert.rb +45 -0
- data/test/unit/lookout-3.0/diff/operations/replace.rb +45 -0
- data/test/unit/lookout-3.0/diff/slice.rb +56 -0
- data/test/unit/{lookout/results/failures/behavior.rb → lookout-3.0/difference.rb} +0 -0
- data/test/unit/lookout-3.0/difference/array.rb +32 -0
- data/test/unit/lookout-3.0/difference/exception.rb +69 -0
- data/test/unit/lookout-3.0/difference/hash.rb +30 -0
- data/test/unit/{lookout/results/failures/state.rb → lookout-3.0/difference/lookout.rb} +0 -0
- data/test/unit/{lookout/results/fulfilled.rb → lookout-3.0/difference/lookout/actual.rb} +0 -0
- data/test/unit/lookout-3.0/difference/lookout/actual/method.rb +7 -0
- data/test/unit/{lookout/runners/console.rb → lookout-3.0/difference/lookout/actual/not.rb} +0 -0
- data/test/unit/lookout-3.0/difference/lookout/actual/not/method.rb +7 -0
- data/test/unit/lookout-3.0/difference/lookout/output.rb +11 -0
- data/test/unit/lookout-3.0/difference/lookout/reception.rb +11 -0
- data/test/unit/lookout-3.0/difference/lookout/warning.rb +11 -0
- data/test/unit/lookout-3.0/difference/module.rb +11 -0
- data/test/unit/lookout-3.0/difference/object.rb +31 -0
- data/test/unit/lookout-3.0/difference/range.rb +11 -0
- data/test/unit/lookout-3.0/difference/regexp.rb +11 -0
- data/test/unit/lookout-3.0/difference/string.rb +29 -0
- data/test/unit/lookout-3.0/difference/symbol.rb +11 -0
- data/test/unit/lookout-3.0/encode.rb +28 -0
- data/test/unit/lookout-3.0/exception.rb +107 -0
- data/test/unit/lookout-3.0/exception/backtrace.rb +75 -0
- data/test/unit/lookout-3.0/exception/unknown.rb +23 -0
- data/test/unit/lookout-3.0/expect.rb +15 -0
- data/test/unit/{lookout/ui/console.rb → lookout-3.0/expect/classes.rb} +0 -0
- data/test/unit/lookout-3.0/expect/classes/exception.rb +41 -0
- data/test/unit/lookout-3.0/expect/exception.rb +63 -0
- data/test/unit/lookout-3.0/expect/object.rb +55 -0
- data/test/unit/lookout-3.0/expect/object/context.rb +120 -0
- data/test/unit/lookout-3.0/expectations.rb +55 -0
- data/test/unit/lookout-3.0/expectations/context.rb +44 -0
- data/test/unit/lookout-3.0/expected.rb +4 -0
- data/test/unit/lookout-3.0/expected/array.rb +19 -0
- data/test/unit/lookout-3.0/expected/classes.rb +4 -0
- data/test/unit/lookout-3.0/expected/classes/exception.rb +7 -0
- data/test/unit/lookout-3.0/expected/exception.rb +24 -0
- data/test/unit/lookout-3.0/expected/falseclass.rb +23 -0
- data/test/unit/lookout-3.0/expected/hash.rb +23 -0
- data/test/unit/lookout-3.0/expected/lookout.rb +4 -0
- data/test/unit/lookout-3.0/expected/lookout/actual.rb +4 -0
- data/test/unit/lookout-3.0/expected/lookout/actual/method.rb +11 -0
- data/test/unit/lookout-3.0/expected/lookout/actual/not.rb +4 -0
- data/test/unit/lookout-3.0/expected/lookout/actual/not/method.rb +11 -0
- data/test/unit/lookout-3.0/expected/lookout/output.rb +27 -0
- data/test/unit/lookout-3.0/expected/lookout/reception.rb +25 -0
- data/test/unit/lookout-3.0/expected/lookout/warning.rb +48 -0
- data/test/unit/lookout-3.0/expected/module.rb +23 -0
- data/test/unit/lookout-3.0/expected/object.rb +24 -0
- data/test/unit/lookout-3.0/expected/range.rb +19 -0
- data/test/unit/lookout-3.0/expected/regexp.rb +19 -0
- data/test/unit/lookout-3.0/expected/string.rb +44 -0
- data/test/unit/lookout-3.0/expected/symbol.rb +35 -0
- data/test/unit/lookout-3.0/expected/trueclass.rb +23 -0
- data/test/unit/lookout-3.0/inspect.rb +39 -0
- data/test/unit/lookout-3.0/interfaces.rb +4 -0
- data/test/unit/lookout-3.0/interfaces/commandline.rb +4 -0
- data/test/unit/lookout-3.0/literal.rb +15 -0
- data/test/unit/lookout-3.0/mock.rb +22 -0
- data/test/unit/lookout-3.0/object.rb +4 -0
- data/test/unit/lookout-3.0/object/not.rb +7 -0
- data/test/unit/lookout-3.0/object/not/receive.rb +9 -0
- data/test/unit/lookout-3.0/object/to.rb +7 -0
- data/test/unit/lookout-3.0/object/to/receive.rb +9 -0
- data/test/unit/lookout-3.0/output.rb +31 -0
- data/test/unit/lookout-3.0/plugins.rb +4 -0
- data/test/unit/lookout-3.0/reception.rb +86 -0
- data/test/unit/lookout-3.0/reception/arguments.rb +23 -0
- data/test/unit/lookout-3.0/reception/arguments/any.rb +15 -0
- data/test/unit/lookout-3.0/reception/arguments/error.rb +4 -0
- data/test/unit/lookout-3.0/reception/arguments/list.rb +19 -0
- data/test/unit/lookout-3.0/reception/arguments/none.rb +15 -0
- data/test/unit/lookout-3.0/reception/error.rb +4 -0
- data/test/unit/lookout-3.0/result.rb +27 -0
- data/test/unit/lookout-3.0/results.rb +4 -0
- data/test/unit/lookout-3.0/results/error.rb +37 -0
- data/test/unit/lookout-3.0/results/failure.rb +21 -0
- data/test/unit/lookout-3.0/results/success.rb +4 -0
- data/test/unit/lookout-3.0/stub.rb +53 -0
- data/test/unit/lookout-3.0/version.rb +4 -0
- data/test/unit/lookout-3.0/warning.rb +47 -0
- metadata +1159 -456
- data/lib/lookout.rb +0 -30
- data/lib/lookout/aphonic.rb +0 -40
- data/lib/lookout/diff.rb +0 -10
- data/lib/lookout/diff/algorithms/difflib.rb +0 -38
- data/lib/lookout/diff/algorithms/difflib/position.rb +0 -92
- data/lib/lookout/diff/formats.rb +0 -7
- data/lib/lookout/diff/formats/hash.rb +0 -53
- data/lib/lookout/diff/formats/inline.rb +0 -39
- data/lib/lookout/diff/formats/unified.rb +0 -57
- data/lib/lookout/diff/group.rb +0 -61
- data/lib/lookout/diff/groups.rb +0 -34
- data/lib/lookout/diff/match.rb +0 -36
- data/lib/lookout/diff/operation.rb +0 -33
- data/lib/lookout/diff/operations.rb +0 -36
- data/lib/lookout/diff/operations/delete.rb +0 -9
- data/lib/lookout/diff/operations/equal.rb +0 -27
- data/lib/lookout/diff/operations/insert.rb +0 -9
- data/lib/lookout/diff/operations/replace.rb +0 -9
- data/lib/lookout/diff/range.rb +0 -91
- data/lib/lookout/equalities.rb +0 -13
- data/lib/lookout/equalities/array.rb +0 -22
- data/lib/lookout/equalities/boolean.rb +0 -9
- data/lib/lookout/equalities/hash.rb +0 -25
- data/lib/lookout/equalities/include.rb +0 -9
- data/lib/lookout/equalities/object.rb +0 -24
- data/lib/lookout/equalities/output.rb +0 -19
- data/lib/lookout/equalities/standarderror.rb +0 -32
- data/lib/lookout/equalities/string.rb +0 -19
- data/lib/lookout/equalities/warning.rb +0 -16
- data/lib/lookout/equality.rb +0 -36
- data/lib/lookout/expectation.rb +0 -69
- data/lib/lookout/expectations.rb +0 -49
- data/lib/lookout/expectations/behavior.rb +0 -20
- data/lib/lookout/expectations/line.rb +0 -29
- data/lib/lookout/expectations/state.rb +0 -31
- data/lib/lookout/expectations/state/warning.rb +0 -26
- data/lib/lookout/mock.rb +0 -20
- data/lib/lookout/mock/method.rb +0 -70
- data/lib/lookout/mock/method/arguments.rb +0 -33
- data/lib/lookout/mock/method/arguments/any.rb +0 -11
- data/lib/lookout/mock/method/arguments/anything.rb +0 -11
- data/lib/lookout/mock/method/arguments/list.rb +0 -15
- data/lib/lookout/mock/method/arguments/none.rb +0 -11
- data/lib/lookout/mock/method/arguments/one.rb +0 -11
- data/lib/lookout/mock/method/calls.rb +0 -11
- data/lib/lookout/mock/method/calls/class.rb +0 -21
- data/lib/lookout/mock/method/calls/exactly.rb +0 -28
- data/lib/lookout/mock/method/calls/instance.rb +0 -25
- data/lib/lookout/mock/method/calls/lower.rb +0 -22
- data/lib/lookout/mock/method/calls/upper.rb +0 -22
- data/lib/lookout/mock/methods.rb +0 -12
- data/lib/lookout/mock/object.rb +0 -12
- data/lib/lookout/object.rb +0 -11
- data/lib/lookout/output.rb +0 -21
- data/lib/lookout/rake/tasks.rb +0 -36
- data/lib/lookout/rake/tasks/gem.rb +0 -49
- data/lib/lookout/rake/tasks/tags.rb +0 -16
- data/lib/lookout/rake/tasks/test.rb +0 -46
- data/lib/lookout/rake/tasks/test/loader.rb +0 -22
- data/lib/lookout/recorder.rb +0 -45
- data/lib/lookout/recorder/not.rb +0 -11
- data/lib/lookout/recorder/tape.rb +0 -21
- data/lib/lookout/recorders.rb +0 -6
- data/lib/lookout/recorders/reception.rb +0 -47
- data/lib/lookout/recorders/state.rb +0 -35
- data/lib/lookout/result.rb +0 -13
- data/lib/lookout/results.rb +0 -25
- data/lib/lookout/results/error.rb +0 -18
- data/lib/lookout/results/error/exception.rb +0 -34
- data/lib/lookout/results/error/exception/backtrace.rb +0 -50
- data/lib/lookout/results/failure.rb +0 -16
- data/lib/lookout/results/failures.rb +0 -6
- data/lib/lookout/results/failures/behavior.rb +0 -5
- data/lib/lookout/results/failures/state.rb +0 -5
- data/lib/lookout/results/fulfilled.rb +0 -5
- data/lib/lookout/results/unsuccessful.rb +0 -31
- data/lib/lookout/runners.rb +0 -6
- data/lib/lookout/runners/console.rb +0 -49
- data/lib/lookout/runners/trackers.rb +0 -5
- data/lib/lookout/runners/trackers/failure.rb +0 -14
- data/lib/lookout/stub.rb +0 -18
- data/lib/lookout/stub/method.rb +0 -105
- data/lib/lookout/stub/methods.rb +0 -18
- data/lib/lookout/stub/object.rb +0 -11
- data/lib/lookout/ui.rb +0 -7
- data/lib/lookout/ui/console.rb +0 -19
- data/lib/lookout/ui/silent.rb +0 -9
- data/lib/lookout/version.rb +0 -5
- data/lib/lookout/warning.rb +0 -7
- data/lib/lookout/xml.rb +0 -17
- data/test/unit/lookout/diff/algorithms/difflib.rb +0 -56
- data/test/unit/lookout/diff/algorithms/difflib/position.rb +0 -92
- data/test/unit/lookout/diff/groups.rb +0 -102
- data/test/unit/lookout/diff/operations.rb +0 -22
- data/test/unit/lookout/diff/operations/delete.rb +0 -45
- data/test/unit/lookout/diff/operations/equal.rb +0 -45
- data/test/unit/lookout/diff/operations/insert.rb +0 -45
- data/test/unit/lookout/diff/operations/replace.rb +0 -45
- data/test/unit/lookout/diff/range.rb +0 -50
- data/test/unit/lookout/equality.rb +0 -113
- data/test/unit/lookout/expectation.rb +0 -47
- data/test/unit/lookout/expectations.rb +0 -36
- data/test/unit/lookout/expectations/behavior.rb +0 -35
- data/test/unit/lookout/expectations/line.rb +0 -29
- data/test/unit/lookout/expectations/state.rb +0 -29
- data/test/unit/lookout/mock/method.rb +0 -143
- data/test/unit/lookout/mock/method/arguments.rb +0 -57
- data/test/unit/lookout/mock/method/arguments/any.rb +0 -11
- data/test/unit/lookout/recorder.rb +0 -11
- data/test/unit/lookout/results/error/exception/backtrace.rb +0 -20
- data/test/unit/lookout/results/unsuccessful.rb +0 -9
- data/test/unit/lookout/runners/trackers/failure.rb +0 -30
- data/test/unit/lookout/stub/method.rb +0 -48
- data/test/unit/lookout/stub/methods.rb +0 -19
- data/test/unit/lookout/xml.rb +0 -55
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cc52934f56620430dc02396b94d8d69b851e598e
|
4
|
+
data.tar.gz: 5478d2367e690c3b8f0bf6f65972929a6ee63aa1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 44aab8e8553f1c1c682082dc2e7476282f4928c488b25b8c6279e8be12fad7273176ff3e31560addaf64d1a05b616c3129a6b00ea9f6a8ad6946238e0a03dbf6
|
7
|
+
data.tar.gz: e1b577bbb0d2d61e1498141ec4e05552e9fb15233bbdcd54a66f0f167feaf92b379bdd81683b9b1b748b9065b1a689cfb7c21b20d9fc5b029c6d1d2e95368a66
|
data/README
CHANGED
@@ -1,14 +1,22 @@
|
|
1
1
|
Lookout
|
2
2
|
|
3
|
-
Lookout is a
|
4
|
-
written as follows
|
3
|
+
Lookout is a unit testing framework for Ruby¹ that puts your results in
|
4
|
+
focus. Tests (expectations) are written as follows
|
5
5
|
|
6
6
|
expect 2 do
|
7
7
|
1 + 1
|
8
8
|
end
|
9
9
|
|
10
|
-
expect
|
11
|
-
|
10
|
+
expect ArgumentError do
|
11
|
+
Integer('1 + 1')
|
12
|
+
end
|
13
|
+
|
14
|
+
expect Array do
|
15
|
+
[1, 2, 3].select{ |i| i % 2 == 0 }
|
16
|
+
end
|
17
|
+
|
18
|
+
expect [2, 4, 6] do
|
19
|
+
[1, 2, 3].map{ |i| i * 2 }
|
12
20
|
end
|
13
21
|
|
14
22
|
Lookout is designed to encourage – force, even – unit testing best practices
|
@@ -21,26 +29,30 @@
|
|
21
29
|
This is done by
|
22
30
|
|
23
31
|
• Only allowing one expectation to be set per test
|
24
|
-
• Providing no (
|
25
|
-
• Providing no setup and
|
32
|
+
• Providing no (additional) way of accessing private state
|
33
|
+
• Providing no setup and tear-down methods, nor a method of providing test
|
26
34
|
helpers
|
27
35
|
|
28
36
|
Other important points are
|
29
37
|
|
30
|
-
•
|
31
|
-
|
38
|
+
• Putting the expected outcome of a test in focus with the steps of the
|
39
|
+
calculation of the actual result only as a secondary concern
|
32
40
|
• A focus on code readability by providing no mechanism for describing an
|
33
41
|
expectation other than the code in the expectation itself
|
42
|
+
• A unified syntax for setting up both state-based and behavior-based
|
43
|
+
expectations
|
34
44
|
|
35
|
-
The way Lookout works has been heavily influenced by expectations
|
36
|
-
{Jay Fields}
|
37
|
-
based at Subversion {revision 76}
|
38
|
-
the work past that revision are due to {Nikolai Weibull}
|
45
|
+
The way Lookout works has been heavily influenced by expectations², by
|
46
|
+
{Jay Fields}³. The code base was once also heavily based on expectations,
|
47
|
+
based at Subversion {revision 76}⁴. A lot has happened since then and all of
|
48
|
+
the work past that revision are due to {Nikolai Weibull}⁵.
|
39
49
|
|
40
|
-
¹
|
41
|
-
²
|
42
|
-
³
|
43
|
-
⁴
|
50
|
+
¹ Ruby: http://ruby-lang.org/
|
51
|
+
² Expectations: http://expectations.rubyforge.org/
|
52
|
+
³ Jay Fields’s blog: http://blog.jayfields.com/
|
53
|
+
⁴ Lookout revision 76:
|
54
|
+
https://github.com/now/lookout/commit/537bedf3e5b3eb4b31c066b3266f42964ac35ebe
|
55
|
+
⁵ Nikolai Weibull’s home page: http://disu.se/
|
44
56
|
|
45
57
|
§ Installation
|
46
58
|
|
@@ -55,7 +67,7 @@
|
|
55
67
|
We’ll begin by looking at state expectations and then take a look at
|
56
68
|
expectations on behavior.
|
57
69
|
|
58
|
-
§ Expectations on State
|
70
|
+
§ Expectations on State: Literals
|
59
71
|
|
60
72
|
An expectation can be made on the result of a computation:
|
61
73
|
|
@@ -74,6 +86,8 @@
|
|
74
86
|
|
75
87
|
Here, the more general ‹#===› is being used on the ‹Range›.
|
76
88
|
|
89
|
+
§ Regexps
|
90
|
+
|
77
91
|
‹Strings› of course match against ‹Strings›:
|
78
92
|
|
79
93
|
expect 'ab' do
|
@@ -89,6 +103,8 @@
|
|
89
103
|
(Note the use of ‹%r{…}› to avoid warnings that will be generated when
|
90
104
|
Ruby parses ‹expect /…/›.)
|
91
105
|
|
106
|
+
§ Modules
|
107
|
+
|
92
108
|
Checking that the result includes a certain module is done by expecting the
|
93
109
|
‹Module›.
|
94
110
|
|
@@ -109,10 +125,20 @@
|
|
109
125
|
Enumerable
|
110
126
|
end
|
111
127
|
|
128
|
+
or the ‹Class›:
|
129
|
+
|
130
|
+
expect String do
|
131
|
+
String
|
132
|
+
end
|
133
|
+
|
134
|
+
for obvious reasons.
|
135
|
+
|
112
136
|
As you may have figured out yourself, this is accomplished by first
|
113
137
|
trying ‹#==› and, if it returns ‹false›, then trying ‹#===› on the
|
114
138
|
expected ‹Module›. This is also true of ‹Ranges› and ‹Regexps›.
|
115
139
|
|
140
|
+
§ Booleans
|
141
|
+
|
116
142
|
Truthfulness is expected with ‹true› and ‹false›:
|
117
143
|
|
118
144
|
expect true do
|
@@ -137,6 +163,8 @@
|
|
137
163
|
computation evaluates to a value that Ruby considers to be either true or
|
138
164
|
false, not the exact literals ‹true› or ‹false›.
|
139
165
|
|
166
|
+
§ IO
|
167
|
+
|
140
168
|
Expecting output on an IO object is also common:
|
141
169
|
|
142
170
|
expect output("abc\ndef\n") do |io|
|
@@ -146,11 +174,35 @@
|
|
146
174
|
This can be used to capture the output of a formatter that takes an
|
147
175
|
output object as a parameter.
|
148
176
|
|
177
|
+
§ Warnings
|
178
|
+
|
179
|
+
Expecting warnings from code isn’t very common, but should be done:
|
180
|
+
|
181
|
+
expect warning('this is your final one!') do
|
182
|
+
warn 'this is your final one!'
|
183
|
+
end
|
184
|
+
|
185
|
+
expect warning('this is your final one!') do
|
186
|
+
warn '%s:%d: warning: this is your final one!' % [__FILE__, __LINE__]
|
187
|
+
end
|
188
|
+
|
189
|
+
‹$VERBOSE› is set to ‹true› during the execution of the block, so you
|
190
|
+
don’t need to do so yourself. If you have other code that depends on the
|
191
|
+
value of $VERBOSE, that can be done with ‹#with_verbose›
|
192
|
+
|
193
|
+
expect nil do
|
194
|
+
with_verbose nil do
|
195
|
+
$VERBOSE
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
§ Errors
|
200
|
+
|
149
201
|
You should always be expecting errors from – and in, but that’s a
|
150
202
|
different story – your code:
|
151
203
|
|
152
|
-
expect
|
153
|
-
|
204
|
+
expect ArgumentError do
|
205
|
+
Integer('1 + 1')
|
154
206
|
end
|
155
207
|
|
156
208
|
Often, not only the type of the error, but its description, is important
|
@@ -166,79 +218,115 @@
|
|
166
218
|
raise StandardError.new('message')
|
167
219
|
end
|
168
220
|
|
169
|
-
|
170
|
-
complicated behavior and will not allow you to pass a ‹Regexp› as a
|
171
|
-
parameter. ‹NameError› is such a class. This may warrant further
|
172
|
-
investigation into whether or not this is a bug, but I’ll leave that up
|
173
|
-
to the reader to decide.)
|
221
|
+
§ Queries Through Symbols
|
174
222
|
|
175
|
-
|
176
|
-
|
223
|
+
Symbols are generally matched against symbols, but as a special case,
|
224
|
+
symbols ending with ‹?› are seen as expectations on the result of query
|
225
|
+
methods on the result of the block, given that the method is of zero
|
226
|
+
arity and that the result isn’t a Symbol itself. Simply expect a symbol
|
227
|
+
ending with ‹?›:
|
177
228
|
|
178
|
-
expect
|
179
|
-
|
229
|
+
expect :empty? do
|
230
|
+
[]
|
180
231
|
end
|
181
232
|
|
182
|
-
|
233
|
+
To expect it’s negation, expect the same symbol beginning with ‹not_›:
|
183
234
|
|
184
|
-
expect
|
185
|
-
|
235
|
+
expect :not_nil? do
|
236
|
+
[1, 2, 3]
|
186
237
|
end
|
187
238
|
|
188
|
-
|
239
|
+
This is the same as
|
189
240
|
|
190
|
-
expect
|
191
|
-
|
241
|
+
expect true do
|
242
|
+
[].empty?
|
192
243
|
end
|
193
244
|
|
194
|
-
|
245
|
+
and
|
195
246
|
|
196
|
-
expect
|
197
|
-
|
247
|
+
expect false do
|
248
|
+
[1, 2, 3].empty?
|
198
249
|
end
|
199
250
|
|
200
|
-
|
251
|
+
but provides much clearer failure messages. It also makes the
|
252
|
+
expectation’s intent a lot clearer.
|
201
253
|
|
202
|
-
|
254
|
+
§ Queries By Proxy
|
203
255
|
|
204
|
-
|
256
|
+
There’s also a way to make the expectations of query methods explicit by
|
257
|
+
invoking methods on the result of the block. For example, to check that
|
258
|
+
the even elements of the Array ‹[1, 2, 3]› include ‹1› you could write
|
259
|
+
|
260
|
+
expect result.to.include? 1 do
|
261
|
+
[1, 2, 3].reject{ |e| e.even? }
|
262
|
+
end
|
263
|
+
|
264
|
+
You could likewise check that the result doesn’t include 2:
|
205
265
|
|
206
|
-
expect
|
266
|
+
expect result.not.to.include? 2 do
|
267
|
+
[1, 2, 3].reject{ |e| e.even? }
|
268
|
+
end
|
269
|
+
|
270
|
+
This is the same as (and executes a little bit slower than) writing
|
207
271
|
|
208
|
-
|
272
|
+
expect false do
|
273
|
+
[1, 2, 3].reject{ |e| e.even? }.include? 2
|
274
|
+
end
|
209
275
|
|
210
|
-
|
276
|
+
but provides much clearer failure messages. Given that these two last
|
277
|
+
examples would fail, you’d get a message saying “[1, 2, 3]#include?(2)”
|
278
|
+
instead of the terser “true≠false”. It also clearly separates the actual
|
279
|
+
expectation from the set-up.
|
211
280
|
|
212
|
-
The
|
213
|
-
|
281
|
+
The keyword for this kind of expectations is ‹result›. This may be
|
282
|
+
followed by any of the methods
|
214
283
|
|
215
284
|
• ‹#not›
|
285
|
+
• ‹#to›
|
216
286
|
• ‹#be›
|
217
287
|
• ‹#have›
|
218
|
-
• Any method whose name ends with ‹?›
|
219
288
|
|
220
|
-
|
221
|
-
|
222
|
-
|
289
|
+
or any other method you will want to call on the result. The methods
|
290
|
+
‹#to›, ‹#be›, and ‹#have› do nothing except improve readability. The
|
291
|
+
‹#not› method inverts the expectation.
|
292
|
+
|
293
|
+
§ Literal Literals
|
294
|
+
|
295
|
+
If you need to literally check against any of the types of objects
|
296
|
+
otherwise treated specially, that is, any instances of
|
297
|
+
|
298
|
+
• ‹Module›
|
299
|
+
• ‹Range›
|
300
|
+
• ‹Regexp›
|
301
|
+
• ‹Exception›
|
302
|
+
• ‹Symbol›, given that it ends with ‹?›
|
303
|
+
|
304
|
+
you can do so by wrapping it in ‹literal(…)›:
|
305
|
+
|
306
|
+
expect literal(:empty?) do
|
307
|
+
:empty?
|
308
|
+
end
|
309
|
+
|
310
|
+
You almost never need to do this, as, for all but symbols, instances will
|
311
|
+
match accordingly as well.
|
223
312
|
|
224
313
|
§ Expectations on Behavior
|
225
314
|
|
226
315
|
We expect our objects to be on their best behavior. Lookout allows you
|
227
316
|
to make sure that they are.
|
228
317
|
|
229
|
-
|
230
|
-
to be:
|
318
|
+
Reception expectations let us verify that a method is called in the way
|
319
|
+
that we expect it to be:
|
231
320
|
|
232
|
-
expect mock.to.receive.
|
233
|
-
|
234
|
-
phone.dial('2125551212')
|
321
|
+
expect mock.to.receive.to_str(without_arguments){ '123' } do |o|
|
322
|
+
o.to_str
|
235
323
|
end
|
236
324
|
|
237
325
|
Here, ‹#mock› creates a mock object, an object that doesn’t respond to
|
238
326
|
anything unless you tell it to. We tell it to expect to receive a call
|
239
|
-
to ‹#
|
240
|
-
|
241
|
-
|
327
|
+
to ‹#to_str› without arguments and have ‹#to_str› return ‹'123'› when
|
328
|
+
called. The mock object is then passed in to the block so that the
|
329
|
+
expectations placed upon it can be fulfilled.
|
242
330
|
|
243
331
|
Sometimes we only want to make sure that a method is called in the way
|
244
332
|
that we expect it to be, but we don’t care if any other methods are
|
@@ -246,43 +334,19 @@
|
|
246
334
|
method and returns a stub object that, again, expects any method, and
|
247
335
|
thus fits the bill.
|
248
336
|
|
249
|
-
expect stub.to.receive.
|
250
|
-
|
251
|
-
phone.hangup
|
252
|
-
phone.dial('2125551212')
|
253
|
-
end
|
254
|
-
|
255
|
-
We can also use stubs without any expectations on them:
|
256
|
-
|
257
|
-
expect 3 do
|
258
|
-
s = stub(:a => 1, :b => 2)
|
259
|
-
s.a + s.b
|
260
|
-
end
|
261
|
-
|
262
|
-
Blocks are also allowed:
|
263
|
-
|
264
|
-
expect 3 do
|
265
|
-
s = stub(:a => proc{ |a, b| a + b })
|
266
|
-
s.a(1, 2)
|
267
|
-
end
|
268
|
-
|
269
|
-
If need be, we can stub out a specific method on an object:
|
270
|
-
|
271
|
-
expect 'def' do
|
272
|
-
a = 'abc'
|
273
|
-
stub(a).to_str{ 'def' }
|
274
|
-
a.to_str
|
337
|
+
expect stub.to.receive.to_str(without_arguments){ '123' } do |o|
|
338
|
+
o.to_str if o.convertable?
|
275
339
|
end
|
276
340
|
|
277
341
|
You don’t have to use a mock object to verify that a method is called:
|
278
342
|
|
279
|
-
expect Object.to.receive.
|
280
|
-
Object.
|
343
|
+
expect Object.to.receive.name do
|
344
|
+
Object.name
|
281
345
|
end
|
282
346
|
|
283
347
|
As you have figured out by now, the expected method call is set up by
|
284
348
|
calling ‹#receive› after ‹#to›. ‹#Receive› is followed by a call to the
|
285
|
-
method to expect with any expected arguments. The body of the
|
349
|
+
method to expect with any expected arguments. The body of the expected
|
286
350
|
method can be given as the block to the method. Finally, an expected
|
287
351
|
invocation count may follow the method. Let’s look at this formal
|
288
352
|
specification in more detail.
|
@@ -291,25 +355,27 @@
|
|
291
355
|
introduce them by giving some examples:
|
292
356
|
|
293
357
|
expect mock.to.receive.a do |m|
|
294
|
-
|
358
|
+
m.a
|
295
359
|
end
|
296
360
|
|
297
361
|
Here, the method ‹#a› must be called with any number of arguments. It
|
298
362
|
may be called any number of times, but it must be called at least once.
|
299
363
|
|
300
|
-
If a method must receive exactly one argument, you can use ‹
|
364
|
+
If a method must receive exactly one argument, you can use ‹Object›, as
|
365
|
+
the same matching rules apply for arguments as they do for state
|
366
|
+
expectations:
|
301
367
|
|
302
|
-
expect mock.to.receive.a(
|
303
|
-
|
368
|
+
expect mock.to.receive.a(Object) do |m|
|
369
|
+
m.a 0
|
304
370
|
end
|
305
371
|
|
306
372
|
If a method must receive a specific argument, you can use that argument:
|
307
373
|
|
308
374
|
expect mock.to.receive.a(1..2) do |m|
|
309
|
-
|
375
|
+
m.a 1
|
310
376
|
end
|
311
377
|
|
312
|
-
|
378
|
+
Again, the same matching rules apply for arguments as they do for state
|
313
379
|
expectations, so the previous example expects a call to ‹#a› with 1, 2,
|
314
380
|
or the Range 1..2 as an argument on ‹m›.
|
315
381
|
|
@@ -317,48 +383,36 @@
|
|
317
383
|
‹without_arguments›:
|
318
384
|
|
319
385
|
expect mock.to.receive.a(without_arguments) do |m|
|
320
|
-
|
386
|
+
m.a
|
321
387
|
end
|
322
388
|
|
323
|
-
You can of course use both ‹
|
389
|
+
You can of course use both ‹Object› and actual arguments:
|
324
390
|
|
325
|
-
expect mock.to.receive.a(
|
326
|
-
|
391
|
+
expect mock.to.receive.a(Object, 2, Object) do |m|
|
392
|
+
m.a nil, 2, '3'
|
327
393
|
end
|
328
394
|
|
329
|
-
The body of the
|
395
|
+
The body of the expected method may be given as the block. Here, calling
|
330
396
|
‹#a› on ‹m› will give the result ‹1›:
|
331
397
|
|
332
398
|
expect mock.to.receive.a{ 1 } do |m|
|
333
|
-
|
399
|
+
raise 'not 1' unless m.a == 1
|
334
400
|
end
|
335
401
|
|
336
402
|
If no body has been given, the result will be a stub object.
|
337
403
|
|
338
|
-
|
339
|
-
around this deficiency you have to use the ‹#yield› method:
|
404
|
+
To take a block, grab a block parameter and ‹#call› it:
|
340
405
|
|
341
|
-
expect mock.to.receive.a.
|
342
|
-
|
406
|
+
expect mock.to.receive.a{ |&b| b.call(1) } do |m|
|
407
|
+
j = 0
|
408
|
+
m.a{ |i| j = i }
|
409
|
+
raise 'not 1' unless j == 1
|
343
410
|
end
|
344
411
|
|
345
|
-
|
346
|
-
last value given will be used repeatedly when all preceding values have
|
347
|
-
been consumed. It’s also important to know that values are splatted when
|
348
|
-
they are yielded.
|
412
|
+
To simulate an ‹#each›-like method, ‹#call› the block several times.
|
349
413
|
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
expect Object.new.to.receive.each.each(1, 2, 3) do |o|
|
354
|
-
class << o
|
355
|
-
include Enumerable
|
356
|
-
end
|
357
|
-
o.inject{ |i, a| i + a }
|
358
|
-
end
|
359
|
-
|
360
|
-
Invocation count expectations can also be set if the default expectation
|
361
|
-
of “at least once” isn’t good enough. The following expectations are
|
414
|
+
Invocation count expectations can be set if the default expectation of
|
415
|
+
“at least once” isn’t good enough. The following expectations are
|
362
416
|
possible
|
363
417
|
|
364
418
|
• ‹#at_most_once›
|
@@ -372,6 +426,8 @@
|
|
372
426
|
• ‹#exactly(N)›
|
373
427
|
• ‹#at_least(N)›
|
374
428
|
|
429
|
+
§ Utilities: Stubs
|
430
|
+
|
375
431
|
Method stubs are another useful thing to have in a unit testing
|
376
432
|
framework. Sometimes you need to override a method that does something a
|
377
433
|
test shouldn’t do, like access and alter bank accounts. We can override
|
@@ -384,13 +440,16 @@
|
|
384
440
|
return something that we can easily control.
|
385
441
|
|
386
442
|
expect 6 do |m|
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
443
|
+
stub(Class.new{
|
444
|
+
def slips
|
445
|
+
raise 'database not available'
|
446
|
+
end
|
391
447
|
|
392
|
-
|
393
|
-
|
448
|
+
def total
|
449
|
+
slips.reduce(0){ |m, n| m.to_i + n.to_i }
|
450
|
+
end
|
451
|
+
}.new, :slips => [1, 2, 3]){ |account| account.total }
|
452
|
+
end
|
394
453
|
|
395
454
|
To make it easy to create objects with a set of stubbed methods there’s
|
396
455
|
also a convenience method:
|
@@ -400,62 +459,115 @@
|
|
400
459
|
s.a + s.b
|
401
460
|
end
|
402
461
|
|
403
|
-
|
404
|
-
you shouldn’t be doing that anyway. In fact, you should never mock or
|
405
|
-
stub methods on value objects.
|
462
|
+
This short-hand notation can also be used for the expected value:
|
406
463
|
|
407
|
-
|
464
|
+
expect stub(:a => 1, :b => 2).to.receive.a do |o|
|
465
|
+
o.a + o.b
|
466
|
+
end
|
467
|
+
|
468
|
+
and also works for mock objects:
|
408
469
|
|
409
|
-
|
410
|
-
|
470
|
+
expect mock(:a => 2, :b => 2).to.receive.a do |o|
|
471
|
+
o.a + o.b
|
472
|
+
end
|
411
473
|
|
412
|
-
|
474
|
+
Blocks are also allowed when defining stub methods:
|
413
475
|
|
414
|
-
|
476
|
+
expect 3 do
|
477
|
+
s = stub(:a => proc{ |a, b| a + b })
|
478
|
+
s.a(1, 2)
|
479
|
+
end
|
415
480
|
|
416
|
-
|
417
|
-
|
481
|
+
If need be, we can stub out a specific method on an object:
|
482
|
+
|
483
|
+
expect 'def' do
|
484
|
+
stub('abc', :to_str => 'def'){ |a| a.to_str }
|
485
|
+
end
|
418
486
|
|
419
|
-
|
487
|
+
The stub is active during the execution of the block.
|
488
|
+
|
489
|
+
§ Overriding Constants
|
490
|
+
|
491
|
+
Sometimes you need to override the value of a constant during the
|
492
|
+
execution of some code. Use ‹#with_const› to do just that:
|
493
|
+
|
494
|
+
expect 'hello' do
|
495
|
+
with_const 'A::B::C', 'hello' do
|
496
|
+
A::B::C
|
497
|
+
end
|
498
|
+
end
|
420
499
|
|
421
|
-
|
500
|
+
Here, the constant ‹A::B::C› is set to ‹'hello'› during the execution of
|
501
|
+
the block. None of the constants ‹A›, ‹B›, and ‹C› need to exist for
|
502
|
+
this to work. If a constant doesn’t exist it’s created and set to a new,
|
503
|
+
empty, ‹Module›. The value of ‹A::B::C›, if any, is restored after the
|
504
|
+
block returns and any constants that didn’t previously exist are removed.
|
422
505
|
|
423
|
-
|
506
|
+
§ Overriding Environment Variables
|
424
507
|
|
425
|
-
|
426
|
-
|
508
|
+
Another thing you often need to control in your tests is the value of
|
509
|
+
environment variables. Depending on such global values is, of course,
|
510
|
+
not a good practice, but is often unavoidable when working with external
|
511
|
+
libraries. ‹#With_env› allows you to override the value of environment
|
512
|
+
variables during the execution of a block by giving it a ‹Hash› of
|
513
|
+
key/value pairs where the key is the name of the environment variable and
|
514
|
+
the value is the value that it should have during the execution of that
|
515
|
+
block:
|
427
516
|
|
428
|
-
|
517
|
+
expect 'hello' do
|
518
|
+
with_env 'INTRO' => 'hello' do
|
519
|
+
ENV['INTRO']
|
520
|
+
end
|
521
|
+
end
|
429
522
|
|
430
|
-
|
431
|
-
|
432
|
-
‹:cnext›. Execute ‹:help quickfix› for additional information.
|
523
|
+
Any overridden values are restored and any keys that weren’t previously a
|
524
|
+
part of the environment are removed when the block returns.
|
433
525
|
|
434
|
-
|
435
|
-
be
|
526
|
+
§ Overriding Globals
|
436
527
|
|
437
|
-
|
438
|
-
let b:undo_ftplugin .= ' | nunmap <buffer> <Leader>M'
|
528
|
+
You may also want to override the value of a global temporarily:
|
439
529
|
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
endif
|
447
|
-
execute 'make' 'TEST=' . shellescape(test) line
|
448
|
-
endfunction
|
530
|
+
expect 'hello' do
|
531
|
+
with_global :$stdout, StringIO.new do
|
532
|
+
print 'hello'
|
533
|
+
$stdout.string
|
534
|
+
end
|
535
|
+
end
|
449
536
|
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
537
|
+
You thus provide the name of the global and a value that it should take
|
538
|
+
during the execution of a block of code. The block gets passed the
|
539
|
+
overridden value, should you need it:
|
540
|
+
|
541
|
+
expect true do
|
542
|
+
with_global :$stdout, StringIO.new do |overridden|
|
543
|
+
$stdout != overridden
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
547
|
+
§ Integration
|
548
|
+
|
549
|
+
Lookout can be used from Rake¹. Simply install Lookout-Rake²:
|
550
|
+
|
551
|
+
% gem install lookout-rake
|
552
|
+
|
553
|
+
and add the following code to your Rakefile
|
554
|
+
|
555
|
+
require 'lookout-rake-3.0'
|
556
|
+
|
557
|
+
Lookout::Rake::Tasks::Test.new
|
558
|
+
|
559
|
+
Make sure to read up on using Lookout-Rake for further benefits and
|
560
|
+
customization.
|
455
561
|
|
456
562
|
¹ Read more about Rake at http://rake.rubyforge.org/
|
457
|
-
² Get information on
|
458
|
-
|
563
|
+
² Get information on Lookout-Rake at http://disu.se/software/lookout-rake/
|
564
|
+
|
565
|
+
§ API
|
566
|
+
|
567
|
+
Lookout comes with an API¹ that let’s you create things such as new
|
568
|
+
expected values, difference reports for your types, and so on.
|
569
|
+
|
570
|
+
¹ See http://disu.se/software/lookout/api/
|
459
571
|
|
460
572
|
§ Interface Design
|
461
573
|
|
@@ -486,20 +598,21 @@
|
|
486
598
|
detail.
|
487
599
|
|
488
600
|
Lookout only allows you to set one expectation per test. If you’re testing
|
489
|
-
behavior with a
|
490
|
-
set. If you’re testing state, then only one result can
|
491
|
-
may seem like this would cause unnecessary duplication
|
492
|
-
While this is certainly a possibility, when you actually
|
493
|
-
avoid such duplication you find that you often do so by
|
494
|
-
interfaces. This kind of restriction tends to encourage the
|
495
|
-
objects, which are easy to test, and more focused objects,
|
496
|
-
simpler tests, as they have less behavior to test, per
|
497
|
-
your interfaces focused you’re also keeping your tests
|
601
|
+
behavior with a reception expectation, then only one method-invocation
|
602
|
+
expectation can be set. If you’re testing state, then only one result can
|
603
|
+
be verified. It may seem like this would cause unnecessary duplication
|
604
|
+
between tests. While this is certainly a possibility, when you actually
|
605
|
+
begin to try to avoid such duplication you find that you often do so by
|
606
|
+
improving your interfaces. This kind of restriction tends to encourage the
|
607
|
+
use of value objects, which are easy to test, and more focused objects,
|
608
|
+
which require simpler tests, as they have less behavior to test, per
|
609
|
+
method. By keeping your interfaces focused you’re also keeping your tests
|
610
|
+
focused.
|
498
611
|
|
499
612
|
Keeping your tests focused improves, in itself, test isolation, but let’s
|
500
|
-
look at something that hinders it: setup and
|
613
|
+
look at something that hinders it: setup and tear-down methods. Most unit
|
501
614
|
testing frameworks encourage test fragmentation by providing setup and
|
502
|
-
|
615
|
+
tear-down methods.
|
503
616
|
|
504
617
|
Setup methods create objects and, perhaps, just their behavior for a set of
|
505
618
|
tests. This means that you have to look in two places to figure out what’s
|
@@ -509,15 +622,15 @@
|
|
509
622
|
set-up object before performing any verifications, further complicating the
|
510
623
|
process of figuring out what state an object has in a given test.
|
511
624
|
|
512
|
-
|
513
|
-
database or deleting files from the file-system.
|
625
|
+
Tear-down methods clean up after tests, perhaps by removing records from a
|
626
|
+
database or deleting files from the file-system.
|
514
627
|
|
515
|
-
The duplication that setup methods and
|
628
|
+
The duplication that setup methods and tear-down methods hope to remove is
|
516
629
|
better avoided by improving your interfaces. This can be done by providing
|
517
630
|
better set-up methods for your objects and using idioms such as {Resource
|
518
631
|
Acquisition Is Initialization}¹ for guaranteed clean-up, test or no test.
|
519
632
|
|
520
|
-
By not using setup and
|
633
|
+
By not using setup and tear-down methods we keep everything pertinent to a
|
521
634
|
test in the test itself, thus improving test isolation. (You also won’t
|
522
635
|
{slow down your tests}² by keeping unnecessary state.)
|
523
636
|
|
@@ -531,7 +644,7 @@
|
|
531
644
|
support for mocks in Lookout is provided through a set of test helper
|
532
645
|
methods that make it easier to create mocks than it would have been without
|
533
646
|
them. Lookout-rack³ is another example of a library providing test helper
|
534
|
-
methods (well, one
|
647
|
+
methods (well, one method, actually) that are very useful in testing web
|
535
648
|
applications that use Rack⁴.
|
536
649
|
|
537
650
|
A final point at which some unit test frameworks try to fragment tests
|
@@ -581,7 +694,7 @@
|
|
581
694
|
|
582
695
|
backtrace.reject{ |l| Regexp.new(@lib).match(File.expand_path(l)) }
|
583
696
|
|
584
|
-
Here ‹@lib› is a ‹String› containing the path to the lib
|
697
|
+
Here ‹@lib› is a ‹String› containing the path to the lib sub-directory in
|
585
698
|
the Mocha installation directory. I reported it, provided a patch five
|
586
699
|
days later, then waited. Nothing happened. {254 days later}¹, according
|
587
700
|
to {Wolfram Alpha}², half of my patch was, apparently – I say “apparently”,
|
@@ -648,6 +761,64 @@
|
|
648
761
|
like a value than ‹BeginEndStorage›. (To reach object-oriented-programming
|
649
762
|
Nirvana you must achieve complete value.)
|
650
763
|
|
764
|
+
§ News
|
765
|
+
|
766
|
+
§ 3.0.0
|
767
|
+
|
768
|
+
The ‹xml› expectation has been dropped. It wasn’t documented, didn’t
|
769
|
+
suit very many use cases, and can be better implemented by an external
|
770
|
+
library.
|
771
|
+
|
772
|
+
The ‹arg› argument matcher for mock method arguments has been removed, as
|
773
|
+
it didn’t provide any benefit over using Object.
|
774
|
+
|
775
|
+
The ‹#yield› and ‹#each› methods on stub and mock methods have been
|
776
|
+
removed. They were slightly weird and their use case can be implemented
|
777
|
+
using block parameters instead.
|
778
|
+
|
779
|
+
The ‹stub› method inside ‹expect› blocks now stubs out the methods during
|
780
|
+
the execution of a provided block instead of during the execution of the
|
781
|
+
whole except block.
|
782
|
+
|
783
|
+
When a mock method is called too many times, this is reported
|
784
|
+
immediately, with a full backtrace. This makes it easier to pin down
|
785
|
+
what’s wrong with the code.
|
786
|
+
|
787
|
+
Query expectations were added.
|
788
|
+
|
789
|
+
Explicit query expectations were added.
|
790
|
+
|
791
|
+
Fluent boolean expectations, for example, ‹expect nil.to.be.nil?› have
|
792
|
+
been replaced by query expectations (‹expect :nil? do nil end›) and
|
793
|
+
explicit query expectations (‹expect result.to.be.nil? do nil end›).
|
794
|
+
This was done to discourage creating objects as the expected value and
|
795
|
+
creating objects that change during the course of the test.
|
796
|
+
|
797
|
+
The ‹literal› expectation was added.
|
798
|
+
|
799
|
+
Equality (‹#==›) is now checked before “caseity” (‹#===›) for modules,
|
800
|
+
ranges, and regular expressions to match the documentation.
|
801
|
+
|
802
|
+
§ Financing
|
803
|
+
|
804
|
+
Currently, most of my time is spent at my day job and in my rather busy
|
805
|
+
private life. Please motivate me to spend time on this piece of software
|
806
|
+
by donating some of your money to this project. Yeah, I realize that
|
807
|
+
requesting money to develop software is a bit, well, capitalistic of me.
|
808
|
+
But please realize that I live in a capitalistic society and I need money
|
809
|
+
to have other people give me the things that I need to continue living
|
810
|
+
under the rules of said society. So, if you feel that this piece of
|
811
|
+
software has helped you out enough to warrant a reward, please PayPal a
|
812
|
+
donation to now@disu.se¹. Thanks! Your support won’t go unnoticed!
|
813
|
+
|
814
|
+
¹ Send a donation:
|
815
|
+
https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=now%40disu%2ese&item_name=Nikolai%20Weibull%20Software%20Services
|
816
|
+
|
817
|
+
§ Reporting Bugs
|
818
|
+
|
819
|
+
Please report any bugs that you encounter to the {issue tracker}¹.
|
820
|
+
|
821
|
+
¹ See https://github.com/now/lookout/issues
|
651
822
|
|
652
823
|
§ Contributors
|
653
824
|
|
@@ -659,7 +830,6 @@
|
|
659
830
|
|
660
831
|
¹ Add an issue to the Lookout issue tracker at https://github.com/now/lookout/issues
|
661
832
|
|
662
|
-
|
663
833
|
§ License
|
664
834
|
|
665
835
|
You may use, copy, and redistribute this library under the same terms¹
|