Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Book: SE@Google Ch 12: Unit Testing #14

Open
ryoarmanda opened this issue Jan 24, 2022 · 0 comments
Open

Book: SE@Google Ch 12: Unit Testing #14

ryoarmanda opened this issue Jan 24, 2022 · 0 comments
Assignees

Comments

@ryoarmanda
Copy link
Contributor

ryoarmanda commented Jan 24, 2022

Book: Software Engineering at Google
Chapter: 12 - Unit Testing

Summary:

Unit tests refer to tests of relatively narrow scope, like a single class or method. Due to it's prevalence compared to functional tests, maintainability of these tests is important for effective work. Maintainable tests, as opposed to brittle ones, are those that engineers write and are unchanging against the system under test; they are ensured that if the tests fail, those indicate real bugs.

To create maintainable tests, some good practices are:

  1. Test via Public APIs: Such tests are more realistic and less brittle because they form explicit contracts. If such a test breaks, it implies that an existing user of the system will also be broken.

  2. Test state, not interactions: Interaction tests check how a system arrived at its result, whereas the engineer should only care what the result is. Interaction details may change from refactoring, yet the result is not, therefore making tests on state to be less brittle.

  3. Make tests complete and concise: Only include information necessary for the test to produce the result, and no other irrelevant or distracting ones.

  4. Test behaviors, not methods: A single method often does a few different things internally. Instead of writing a test for the method, write a test for each behavior of the method, that is an assertion that the system makes when given certain inputs in a certain state.

    • Behaviors can be expressed as a "given"-"when"-"then" sequence, which is a good framework to structure behavior-driven tests
  5. Don't put logic in tests: In tests, choose straightforward code over clever logic, as logic creates another level of complexity to tests that we might fall into. Consider duplicating data when it makes the test more descriptive and meaningful.

  6. Write clear failure messages: A good failure message clearly distinguishes the expected from the actual state and gives more context about the result.

  7. DAMP, not DRY: While system code are generally DRY (Don't Repeat Yourself), opt for DAMP (Descriptive and Meaningful Phrases) in tests, as to make the tests understandable within its own and not to fully inspect test files to comprehend them.

    • Duplicate data, constants, interaction sequence, etc, reasonably
    • If test suite calls for shared values, use helper methods to create a default value that can be overridden by arguments.
    • If test suite calls for shared setups, override the initial values to the context of the test to minimize confusion.
    • Validation helpers should assert a single conceptual fact about their inputs, rather than a collection of them in one.
@ryoarmanda ryoarmanda self-assigned this Jan 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant