"Assemble-Activate-Assert":is the pattern that all UnitTest cases follow, so arranging, naming, and formatting code to reflect the pattern is a good idea:
All TestCases...
- Assemble the data resources they intend to use.
- Activate a target method. -- sometimes referred to as "TheMoneyLine"
- Assert that some side-effect, from that method, is within tolerance.
ToDo: See ArrangeActAssert (and consider condensing!)
All TestCases follow some variation of this pattern:
def test_case
a = assemble()
q = a.activate(41)
assert{ q == 42 }
end
All
TestCases first
Assemble the data resources they intend to use.
Then they Activate a target method. (Preferrably the one you name your real test case after!)
Then they Assert that some side-effect, from that method, is within tolerance.
AssembleActivateAssert seems to be used primarily in the RubyLanguage community.
The ArrangeActAssert term seems to be more popular in the JavaLanguage community.
I might say that AssembleActivateAssert/ArrangeActAssert is a pattern that test cases should follow.
I've certainly seen and even tests that don't follow these patterns.
The tests might be improved by following the AAA pattern, but they did work and were automated tests, even without following the AAA pattern.
Specific deviations I've seen are...
- Doing assertions in the "Arrange/Assemble" section of the test -- typically to assert that things have just been successfully initialized to a certain expected state needed by the code calling the ClassUnderTest (the "Act(ivate)" step) to be testing the intended scenario.
- Assertions mixed with ClassUnderTest calls -- mixing "Act(ivate)" and "Assert" steps. This may be done to "tell a story" or test a full scenario: Do step 1, with (assert) this result, followed by step 2, with this result, then step 3, with this result.
- Making this three separate tests is possible, but may duplicate all the code of steps 1 and 2 in test 3, causing maintenance problems if the code in steps 1 or 2 change. Of course test 3 could call test 2, which calls test 1. But if test 1 fails, all three fail at that point -- which still masks potential failures in steps 2 and 3. And heavy code reuse in tests can obscure their intent -- which is one of the most important aspects of tests.
- Tests may loop over a number of scenarios, invoking the ClassUnderTest and doing assertions in each loop. This may be "due to" JUnit's (JavaUnit's) lack of data driven test support. But it's a limitation we generally have to live with.
--
JeffGrigg
For any test case you can show me, worth the name, no matter how defactored or scripted or behaviorized it may be, I can point to its Assemble, its Activation, and its Assertion.
It's not "should follow", it's "defines". --PhlIp
Also known as: ArrangeActAssert