Metacello new
baseline: 'PowerAssert';
repository: 'github://dupriezt/PowerAssert';
load.
Run the following test (available on the PowerAssertExamples class):
testPowerAssertExample1
| array |
array := { 2. 4. 6 }.
self powerAssert: [ (array at: 2) % 2 ~= 0 ].
The usual window informing you that the test failed opens.
But more interestingly, another window opens, showing you the details of the computation of the asserted expression. It features:
- top: the asserted expression
- middle: a list of the AST nodes that were evaluated, with the value they had, in the order in which they were evaluated. Selecting an item in this list highlights the corresponding part of the asserted expression.
- bottom: a pharo inspector on the value of the selected AST node
- Some compilation optimisations throw off powerassert, giving strange results. For example, the
Number>>#to:do:
method (it is inlined by the compiler). - The tests on the PowerAssertExamples class give the expected results, and can be used for demonstration
- The tests on the PowerAssertTest class may fail
You can replay an execution captured by a power assert.
The following tests picks a divisor of 60 at random and makes the division. It passes most of the time, except when 0 is picked, resulting in a ZeroDivide exception.
PowerAsserterExamples>>#testPowerAsserterReplayerExample
| divisorsOfSixty |
divisorsOfSixty := { 0. 1. 2. 3. 4. 5. 6. 10. 12. 15. 20. 30. 60 }.
PowerAsserter new assert: [ (60 / (divisorsOfSixty at: divisorsOfSixty size atRandom)) isInteger ]
When this test fails, the PowerAssert Visualiser window opens, showing the recorded values during the assertion's execution.
In particular, we see that the value of the random index was 1, so the first divisor was selected (0).
To replay the buggy execution, click on the Replay button. This opens a PowerAssert Replayer window.
This window behaves like a debugger on a fresh execution of the assertion. From top to bottom, it contains:
- the context stack (the top of the stack is at the top)
- stepping buttons + inspect buttons
- a view of the assertion's code
- the value stack of the selected context (the top of the stack is at the bottom)
- an inspector on the "replay value". If the node the execution is on has had a value recorded for it by PowerAssert, the recorded value will be shown in this inspector
Right now, the current node is divisorsOfSixty size
. This result of this message-send is deterministic, so it does not matter whether you replay it or not. Click Over.
Now, the current node is divisorsOfSixty size atRandom
. This message-send is not deterministic. You can see in the replay value inspector that the recorded value for this message is 1. Click Over (Replay) to use the recorded value instead of executing this message-send.
As you can see on the value stack, the top value (i.e. the result of the previous message-send) is indeed 1, the recorded value. If you continue to step over, you will get an exception.
By clicking Debug and checking the value of the unhandledException variable, you can see that this exception is indeed the division by zero.
If you go back to the PowerAssert Replayer and click Restart, you can restart the assertion's execution. Note that this is in fact a fresh execution of the same assertion block, but with the same replay data.
This time, if you press over instead of Over (Replay) on the atRandom
message-send you will (likely, this is random after all!) get a different index (7 on the picture). If you keep stepping over, the execution will terminate normally instead of signalling an exception.
- If the same ast node is executed multiple times during the assertion, the replay will use the value of the first execution of this node when replaying all executions of this node.
- Step buttons work on the top context of the stack. Probably not the other contexts.