I want to come in with a different answer here, in favor of adding these comments.
TL;DR Use these comments when they make sense. I'm all for it.
But first, I want to be very clear here that this answer is only scoped to the specific given/when/then (or act/arrange/assert, same difference) comments. I agree with the people who are against them when we're talking about code comments in general (e.g. used to fix badly structured code, code should be evident to read, ...), but I think there is a special case for the GWT comments that is not being accounted for in their answers.
GWT (or AAA) is a known concept because it so accurately describes the vast majority of test implementations. You set up some scenario (given/arrange), you let it play out (when/act), you confirm that it behaved the way it needed to in the given scenario (then/assert).
These three sections of the testing process are discrete and should be done one after the other. It would be illogical to e.g. change something about the scenario after you've already acted on it (because then you've just invalidated the first act) or test something before you've acted on the scenario (because what is there to test if not the act itself?).
These three steps are also discrete parts of the developer's mindset when working on a test. Whenever you want to make any change you a test, or you're writing it, you need to be innately aware of whether you're arranging, acting or asserting, because you need to always respect the previous paragraph (i.e. never doing anything out of order).
Having established these points, there is still one other solution: use discrete submethods. Something along the lines of:
public void MyTest()
{
Arrange();
Act();
Assert();
}
This follows the usual guideline on code comments that it's better to structure your code readably than it is to add comments to aid difficult to read code. I actually agree with this advice for real code, but not for unit tests. Tests can get very hairy very quickly when any of its steps require more than a handful of lines, and the submethods introduce several negatives for a testing context:
- The test is no longer readable from top to bottom, you need to go and jump to different submethods to understand it. Sure, you could maybe put your submethods in the same order, but then you've still introduced additional fluff (method signature and braces) inbetween the relevant bits - at best this approach would be equally as bad as adding a
// when
comment.
- Scopes/closures are making it hard for variables/data to flow from one part of the test to the next. Not that it can't be done, but in order to make it work now, it requires additional complexity. Because a test is a very restricted scope, it's reasonable for it to define all of its content in a "global" scope (i.e. scoped to the whole test), but the submethods make this harder to achieve.
So it detracts from readability (first bullet point), and it adds complexity (second bullet point). That's not great.
This is why I consider given/when/then (or act/arrange/assert) comments valid additions to a test body. To summarize the benefits:
- It can help a developer quickly navigate to the correct section of a test.
- It adds an easy visual gauge to spot if you've put some logic in the wrong section
- It does not meaningfully decrease readability (compared to other possible solutions to the first two bullet points)
- It does not introduce logical complexity (compared to other possible solutions to the first two bullet point)
So yeah, use these comments when they make sense. I'm all for it.
Just to point out some edge cases that people might point out in the comments:
- Integration tests are a different breed of test where GWT/AAA is not as easy to maintain, as integration tests often entail a more complex orchestration, e.g. GWGWGWT or GWTGWTGWT
- I'm not saying that a dev would be unable to navigate the code without these comments. I'm saying that it adds more value than it adds problems, so it's a net positive.
- If there is a specific case where these comments don't add a net positive, then don't use them there. That's not an argument against not using these comments in general, though.