I’d like to propose a change to the behavior of subjectAction that makes it more useful for behaviorally driven testing. First, I’ll motivate the change by showing a typical BDD pattern that I imagine we’ve all encountered. Then, I’ll make an implementation suggestion. The first doesn’t depend on the second; if the specific suggestion doesn’t fit, another one could be come up with so long as enough people agree with the problem.
How often have you done this?
```
describe(@“response to a network request or whatnot”)
subjectAction(^{ something that triggers the response})
context(@“When there’s a success of type A”);
context(@“When there’s a success of type B”);
context(@“When there’s a success of type C”);
. . . .
context(@“when there is an error”)
beforeEach(^{
response = responseThatTriggersError;
});
it(“should display an alert”);
context(“when the user touches ‘ok’”)
beforeEach({
[[UIAlertView currentAlertView] dismissWithOKButton];
});
```
. . . . only to realize now you have to go back, remove the subject action, and put the response-triggering call at the right point in every sub context, because the response that triggers the error is now occurring *after* the touch on the (non-existing) alert?
SubjectAction is fantastically useful. But it’s fighting with behaviorally testing nested behaviors, and I don’t think it needs to.
Why is this the case? It’s because subjectAction is currently defined to be executed before every example, no matter how deeply nested. This is great for some cases, and rotten for others. In the above case, for example, what one would prefer is for there to be a subjectAction ‘firewall’ at ‘when there is an error’. The subjectAction should be triggered so that the rest of the behavior that proceeds from there - the alert in this case - can be tested. Ideally, you could even start *another* subjectAction within that behavior block!
One can implement this manually, by passing an ‘action’ object and calling it manually. But that’s exactly the overhead that subjectAction is intended to avoid.
Here’s a proposed solution: currently, ‘describe’ and ‘context’ are synonymous. This was done, IIRC (PC, Adam Milligan - maybe Sam or someone else remembers the details?) because both terms are used to about the same effect in two different testing libraries, and this made users of both more at home in Cedar.
Instead, ‘describe’ should be a subjectAction firewall. That is, SAs get fired by a describe. Thus the above testing could be accomplished by replacing the ‘context(@“when there is an error”)’ line with ‘describe(@“when there is an error”)’.
If there is enough support for this specific solution, I’ll take a hand at implementing it. If there isn’t, but the problem is agreed with, I’m game to hear other suggestions for implementation.