Skip to content

Writing Tests

pospi edited this page May 1, 2017 · 1 revision

The testing expectations for this repository are largely based on this article, which includes some excellent advice. We recommend you read it in full.

In brief, here's how you should write your tests:

React components

Keep things simple, and avoid testing React internals.

  • Minimal component test to verify that the component actually renders. 90% of the time, you will only need a single "it renders" test for your component.
  • Avoid verifying tags or class names. These change often and tests just make changing the code harder.
    • However, if there is a particular classname or tag presence required for some other unrelated code (eg. a non-React library) to function, then you should definitely add a test for its presence.
  • Verify important callbacks or props, but keep it minimal.
  • The need to test logic inside a component might signal the need for refactoring.

Higher-order component factories

Higher-order component factories are just functions which accept a component and return a new wrapped component with additional logic. You can find these in the ui-bindings package folder.

Since these components typically only combine GraphQL queries and data from Redux store selectors, there's really no point in testing them- these things would both require a lot of mocking and the Redux layer should be explicitly tested anyway. As for GraphQL queries, since they are built with JS template literal tags they will break at compile time if defined incorrectly and this will be caught by your Webpack build process.

There may be other specific things which need to be tested in future, this section is left open to exploration...

Redux actions & reducers

Testing action creators on their own adds no benefit, since you're basically writing the action creator a second time to test it.

Instead, test the action creators in combination with their associated reducers together. You will also want to export initialState from your reducer files so it can be used as the starting state for each reducer test.

Note that there's no need to test series' of reducer actions, since each separate action's handling should be an independent operation. If there is a requirement in your app for one action to fire before another can successfully run, you're doing it wrong.

Asynchronous Redux actions / sagas

:TODO:

We aren't using these much and we may deprecate them eventually since all async logic is currently API-based and managed by GraphQL. Note that if needed there are examples of these tests in the article linked above.

Also note that you shouldn't ever be using 'normal' asynchronous actions anyway, since sagas are much more easily testable as nothing extra needs to be mocked.

Service files

Test as you would 'normal' code. Since the structure of these is up to you, it's also up to you to write them in an easily testable manner. Pure functions wherever possible, and functional core / imperitive shell!

App as a whole

:TODO: work out the best way to approach this.

Some integration tests will be needed. We'll probably only want to do these for 'critical path' things like logging in, etc. See also Integration Tests Are a Scam.