GoGaRuCo 2010

Eschew Obfuscation and Omit Needless Words: Writing Clear Acceptance Tests

Eschew Obfuscation and Omit Needless Words: Writing Clear Acceptance Tests

by Elisabeth Hendrickson

In her presentation at GoGaRuCo 2010, Elisabeth Hendrickson addresses the importance of writing clear acceptance tests using modern frameworks like Cucumber. The main theme revolves around enhancing communication between technical and non-technical stakeholders by employing Domain Specific Languages (DSLs). While Cucumber allows for natural language tests, Hendrickson emphasizes that a well-defined DSL is only the beginning; clarity and conciseness in test writing are crucial.

Key Points Discussed:

- Introduction to Acceptance Testing:

- An anecdote about her first conference presentation highlights the importance of clarity in communication.

- The session focuses on the importance of treating acceptance tests with the same care as source code.

  • Communicating Clearly:

    • Acceptance tests should reflect clear communication using a common language understood by all team members.
    • The principles from 'The Elements of Style' by Strunk and White are paralleled in writing acceptance tests.
  • Clarity in Tests:

    • Cucumber tests often become verbose, leading to obfuscated intentions. A simple example illustrates how to refactor Cucumber tests for clarity by focusing on core intent rather than UI details.
    • The importance of omitting unnecessary words to maintain the essence of what needs testing is stressed significantly.
  • Refining Acceptance Tests:

    • Emphasizes structuring tests with a single topic per test scenario, advocating for organized tests.
    • Explaining that acceptance tests should serve as executable documentation to ensure shared understanding among all parties involved.
  • Maintaining Clarity and Expressiveness:

    • Cautions against the disconnect that can arise when developers rely too heavily on technical jargon, urging a focus on using clear language.
    • Highlights the significance of balancing expressiveness and brevity in testing language to enhance both clarity and usability.

Conclusions and Takeaways:

- Acceptance tests are a vital tool for alignment on customer expectations.

- Clear and concise acceptance tests improve communication across teams, ensuring everyone understands functionalities being developed.

- The goal is to create acceptance tests that not only validate features but also enhance collaboration and customer understanding. Hendrickson concludes by encouraging an ongoing dialogue about improving practices surrounding acceptance tests, reiterating their value in delivering functional software and meeting customer needs.

00:00:11.120 I want to share a brief anecdote before I get into the main content of my talk. The very first time I stood in front of a conference room full of people and gave a talk was in 1997 at a vendor tool conference focused on test automation. I was presenting a technique that involved some deep magic with a fascinating, albeit undocumented, aspect of the programming language. I prepared 25 slides that were incredibly code-dense, and when I get nervous, I tend to speak faster. This tendency led me to rush through those slides, and by the time I reached the end, I realized I had used up 25 minutes of my 45-minute speaking slot without any sense of time. I looked at the audience and noticed they all seemed puzzled. I asked, 'Did I go too fast?' but the audience continued to look at me in confusion, except for one person in the front row who said, 'No, that wasn't too fast; that was perfect!' I suspect he understood everything because he was likely intimately familiar with the topic. Yesterday, while sitting in the audience, I realized that I was in front of a room full of people who are much smarter than I am.
00:01:20.560 I am more concerned about whether you, as the audience, will find this session useful. Yesterday, I learned that there are many people here who program in Ruby and are involved in testing, especially those who drive development with tests. I know someone asked how many use Cucumber, but I forgot to ask how many are actually using it. So, how many of you use Cucumber? Wow, that's a lot of hands! That's fabulous, but I want to clarify that this talk isn't solely about Cucumber even though all the examples I’ll use are taken from it.
00:01:37.040 Now, I'm curious to know how many of you take the time to properly maintain your code. Do you refactor, ensure your method and class names are evocative, and remove duplication? Let’s see a show of hands. That's great, but now how many of you treat your acceptance tests the same way? Yes? Well, there are many fewer hands, which makes me a bit sad. But that's okay because this talk isn’t about how to treat your tests like code or how to refactor them. It's also not a technical talk about Ruby or other specific tools, though some technical details may sneak in. Instead, this talk is about being nice to humans – all of you, remember you are human as well.
00:02:52.400 Being nice means communicating in a language that everyone on your team can understand. While some teams might communicate in Ruby or code, chances are your team speaks in English, or at least English is the primary language used. Where better to find guidance for effective communication than in the timeless classic 'The Elements of Style'? As Ryan Henricks reminded us yesterday, tests are a means of communication, so our tests should follow some fundamental rules. Let's take a look at one of the key rules from this book: begin each paragraph with a topic sentence and end in conformity with the beginning.
00:03:40.080 Isn’t it interesting that Strunk and White were indirectly discussing acceptance tests? Let’s reflect on that. Instead of 'scenario,' we could use 'paragraph,' and we should strive for evocative names. But let’s also ensure our expectations are aligned with our statements and names. For example, looking at Cucumber tests, I see many suites where the tests are either verbose or muddy in their intent. We tend to get lost in details that hardly clarify what is being tested. This is a common issue I face with testing frameworks. When looking at a suite of tests, I often find myself thinking, 'What is the intent here?' If I can’t easily determine what is being tested, something needs to change.
00:04:38.080 Let’s explore how to refactor these tests for clarity. Suppose I’m using a trading system called Magix, where users called players wish to trade commodities. If I’m logged in as the fairy godmother on the make offer page and we have a convoluted series of conditions to meet, how can we boil that down to its essence? Often, tests become swamped with UI details that are extraneous to the logic we’re trying to validate. Tests should focus on the intent – here, to make an offer – rather than on the minutiae of filling in the fields of a UI form. This is a widespread practice, and it's essential, especially in acceptance testing.
00:05:53.440 Now that we’ve refactored our test for clarity, we should also adopt another principle: omit needless words. This echoes Strunk and White's Rule number 13. We want our test to express its essence without any unnecessary details. When reviewing our test, if we find any statements that refer to the UI and distract from the main intent, we should consider whether we can eliminate them.
00:06:32.800 We must ensure our test remains focused. For instance, if our expectations are to verify that an offer is created and visible on the market, we do not need to burden our test with UI components unless we are specifically testing the UI. By allowing such superfluous details to seep into our tests, we obscure the intent – the customers want to express their intent about the system clearly. Ultimately, our tests should convey what matters: making offers and seeing them represented clearly in our system.
00:07:59.040 Moving forward, I would like to highlight that clarity and brevity should dominate our acceptance tests akin to how one might approach English in writing. In fact, Strunk and White’s advice can be applied here predominantly: one topic per paragraph. Following Rule 15, we should also put similarly corresponding ideas in similar forms. In Cucumber, this means using scenario outlines and tables to articulate complex situations without creating overly lengthy tests. We must keep tests organized during longer acceptance tests; this will keep both developers and stakeholders in sync regarding expectations.
00:09:02.720 One effective way to be nice to humans is to allow them to express themselves in simple yet meaningful ways. Consider a situation where Jack offers one magic bean bag and T-Bell offers five. If we are too literal in our step definitions, this can stifle the narrative. Instead, we should encourage users to express scenarios as naturally as possible. Cucumber allows us to utilize regular expressions, which can be instrumental in creating flexible and human-friendly steps. This flexibility will help alleviate confusion and miscommunication.
00:10:09.440 Now, let's take a moment to understand the importance of creating these clear acceptance tests. Our approach to acceptance tests ultimately informs how well we understand customer expectations. It’s crucial that we focus on using the tests as a communication tool that aligns with customer needs and the core philosophy of user acceptance. Our tests should capture the essence of what our software aims to achieve, enabling stakeholders to review them meaningfully.
00:11:06.720 Acceptance tests, at their core, should serve as executable documentation that avoids path dependencies. As we become accustomed to writing them, acceptance tests become an important aspect of ensuring shared understanding among teams. They should allow effective communication across all parties – developers, testers, and stakeholders alike. If we face pushback in utilizing natural language in acceptance tests, it highlights a need for further collaboration in developing these tests.
00:12:03.680 Now, I’d like to shift gears and mention the importance of maintaining clarity in our acceptance tests. As developers, we inherently lean toward coding languages and abstract terminologies unique to our domain. This leads to a disconnect, especially when we forget to utilize clear human languages. Ensuring that potential language barriers don’t impede our work is vital; acceptance tests should expand access to knowledge and clarity rather than constraining them.
00:13:26.400 As we tread further into crafting our acceptance tests, I cannot stress enough the importance of clarity. As George Orwell pointed out, "if thought corrupts language, language can also corrupt thought." The way we express our acceptance tests directly influences our understanding of the functionalities we are building. This can unravel into confusion and miscommunication that ultimately leads to tragic misunderstandings weeks later.
00:14:05.440 It’s vital to emphasize that acceptance tests form an essential alignment tool that can bridge the communication gap. We must focus on maintaining clear acceptance tests to ensure that we meet customers’ expectations. When acceptance tests transform into self-explanatory documentation, they enable clients and stakeholders to engage effectively, providing a clearer understanding of the functionalities being implemented.
00:15:37.920 In conclusion, I'd like to extend my gratitude to Steve Conover for reminding me of George Orwell’s wisdom. The collaboration on writing acceptance tests can be incredibly enriching for teams, enabling us to maintain a focus on delivering customer value while ensuring clarity throughout all phases of a project. Moreover, I will share my materials online later today when they are up on GitHub.
00:16:20.480 As we approach the conclusion of my talk, I'm eager to address any questions or discussions on the topics we've covered. I want to encourage you to share your experiences and thoughts regarding acceptance tests. The conversation around improving our practices related to acceptance testing can lead to more effective testing environments. So, feel free to ask, dive into the nuances, and let’s keep the discussion going!
00:17:39.920 Regarding acceptance tests written in natural language, it is an essential conversation to have. When creating acceptance tests, we should balance the expressiveness of our language with the need to avoid redundancy and repetition. This leads to the realization that we can code our tests using a small set of step definitions that may reflect multiple scenarios. However, avoiding redundancy should not come at the cost of clarity. Thus, while striving for DRY principles in our tests, we also need to maintain readability and natural language fluidity.
00:21:03.520 Overall, my goal for today was to emphasize the need for balance: writing acceptance tests that are clear, expressive, and aligned with the core needs and expectations of customers. Let’s work together to develop acceptance tests that serve as effective communication tools, ensuring we can deliver valuable and functional software while fostering collaboration among all stakeholders involved. Thank you!