Arrange Act Assert Alternatives

2020-08-12 13:02发布

问题:

The general question is are there alternative patterns to AAA for unit testing? If, yes, would be very interesting to see some examples and hear about their pros and cons.

And as the simplest example of AAA test (in c#, using var for the sake of simplicity):

// Arranging
var annualSalary = 120000M;
var period = 3; // for a quarter profit
var calc = new SalaryCalculator();

// Acting
var result = calc.CalculateProfit(annualSalary, period); 

// Assertion
Assert.IsEqual(40000, result);

回答1:

I like something that is not so much an alternative to AAA, but rather a variation. I think of it as Arrange-Assert(not)-Act-Assert, but others have called it a Guard Assertion. The idea is to have an assertion that ensures the desired result of the Act is not already present before the act. There's a good discussion of it here.



回答2:

There is another notation from Behavior-driven development: Given - When - Then. Examples for c# is SpecFlow and for Jasmin for JavaScript. Both resource are full of examples of using this notation. The GWT approach is typically used in a Behavior Driven Development and Aspect Oriented Programming.



回答3:

Some of the earliest mocking frameworks (in the .Net world at least) forced you to use the Record/Replay pattern. I say force because I don't find it very natural or readable and there was no alternative back then.

This spawned a new race of isolation frameworks promoting the AAA form, which I find to be the most intent-revealing approach. More about this here.



回答4:

when you are using parameterized testing then often you can move 'arranging' or 'given' part to parameters. but still, the principle remains



回答5:

Another common pattern used in unit testing is Four Phase Test Pattern:

  1. Setup
  2. Execute
  3. Check
  4. Teardown

The first steps are essentially the same as in the AAA Pattern. However, I find the Four-Phase Pattern better suited to languages where you have to clean up after yourself, for example, C or C++. Step 4 (teardown) is where you free any allocated memory, or destroy objects you created for the test.

In situations where you do not allocate any memory, or a garbage collector takes care of deallocation, the fourth step goes unused most of the time, so it makes more sense to use the AAA Pattern.

In C++, for example, the above test might be:

// Setup
int annualSalary = 120000;
int period = 3; // for a quarter profit
int result;
SalaryCalculator calc = new SalaryCalculator();

// Execute
result = calc.CalculateProfit(annualSalary, period); 

// Check
CHECK_EQUAL(40000, result);

// Teardown
delete calc;