lookout 2.3.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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¹
|