This is a blog post in response to dave ruperts blog post about his struggle to get started with unit testing in todays front-end development landscape.
So hey Dave, or whoever is reading this - you are not alone. 🙂
I'd love to share my personal experience with you about how I got into the culture of creating automated tests for my work and how it changed my workflow for the better.
In this post I'm covering:
- what are the benefits of unit testing?
- what other types of testing is there?
- and what is appropriate for which type?
For me it started as a goal. Nothing is more embarrassing than delivering something to see it broken in production. I knew we were keeping breaking stuff and we had no way of monitoring that backwards progress. We were coding in circles, cleaning up after each other and getting more and more grumpy about the other developer not knowing what they just have broken.
Getting a better understanding about requirements
So I just introduced ava, wrote a few simple acceptance tests and soon the others started to adopt it 😃. Everybody felt more obligated to keep the unit tests green and we saw better results. You can set up git commit
hooks to run tests before anything gets pushed. Thanks to husky and lint-staged.
Writing unit tests is something you get better and better while doing it. I also carefully read a lot before diving into the topic, but you just have to give it a go to really see how you could test your application. Sometimes you know what you will need, and sometimes you can write the test before anything else.
I tried to test functionality as a whole at first. Exactly what codeahoy experienced is first instinct but this is very backwards.
Here is a simple set of rules you can follow, if you get too overwhelmed:
- If you start thinking too much about the API, consider smaller aspects and chunks of the function first.
- Too much indentation in your function is a sign that these parts can be extracted to a re-usable unit.
- Identify how the result of the function is used. They can of course build on top of each other, but the smaller the unit, the better you can perform unit tests, since it is easier to come up with expectations.
What is the appropriate tooling?
First, I believe there is other tooling more appropriate for making sure that your UI implementation looks nicely in all kinds of browsers or screen sizes.
Unit testing is more appropriate for making sure, that the outputs of a function match with the expectations you have about that function.
Anything with side effects like modifying something outside the scope of a function is pretty tough to test as a unit. Bad examples for unit tests are:
- Did the animation work?
- Did the screen size break the layout?
- Was the form submitted with the correct data?
Even though you can test parts of that in isolation, like the data validation within a form, for those tasks listed above you need to employ different approaches.
Headless browser testing
There is nightmarejs or nightwatch to test your app/website in headless browsers like phantomjs, Puppeteer or Selenium.
Those fire up a browser, mimick a user with the behavior you describe (click there, enter that into that field, submit the form) and perform tests based on expectations. But there you only test if the DOM acts as you carefully defined.
Then there are helpers like PhantomCSS, which builds on top of casperjs on top of phantomjs. With that you can do regression tests, which can help you in automating displaying different content in different situations and look if this matches up to your expectations.
Living styleguide with Storybook or KSS
Then there is Storybook - a UI component documentation framework to see and test components in isolation - manually though. This helps to see the components work in isolation. This is the evolved form of living styleguides generated from KSS.
What to invest time into?
I found that unit tests are the most effective and maybe also fastest to set up. They prove that functions work as expected and even after changing, moving, refactoring code, your tests prove that they still work.
If you have plenty of components that you think will have different looks in different situations, you should look into KSS or storybook. However with regression testing which is the toughest to set up, you can really make sure that nothing breaks your expectations. This is a partly manual test though.
Unit testing framework of choice?
In the screenshot you saw above, I'm using ava.
ava helped me a lot to get into the culture of unit-testing my code. With its zero setup and easy API, It is so fulfilling to quickly get started and see the tests go green in the terminal. Especially with the watcher functionality, you get almost instant feedback about what went wrong.
You can also combine it with NYC - a tool to generate code coverage reports based on the functions it ran through. You can configure it to show you which functions were run or not, which is very helpful to see what scenarios you are actually missing.
They even show optional parameters, executed if branches and how often.
Conclusion
I believe unit-testing backend code is a lot easier to get started with, where single functions are written to perform single tasks. In front-end, most of the time everything is intertwined and it is so easy to make one function or event handler do a lot of stuff at the same time. So unit testing forces you to split your functions into logical bits. Which is the very first step towards creating testable code. How do you mock a submit event for a form? Other than collecting form data, sending the API request and sending the confirmation in one go, you can split it into their own functions and test those.
So go out there now and write tests. Hopefully this article helped you to get a better understanding for what ways there are - other than unit tests - how you can make sure you don't break anything.
How do you charter unknown server territory?
Don't get stuck connecting forms and servers.
Get free on-spot advice delivered to your inbox.