“But Testing Sucks!”

How to Build Testing- and Quality-Driven Culture

by Jason Lengstorf
@jlengstorf  ·  jason@lengstorf.com

Slides: git.io/test-culture

We all know testing is important

...so why isn’t it happening?

There are plenty of “reasons” not to test:

  • “We don’t have time to write tests!”
  • “Where do we even start with testing?”
  • “Testing slows us down!”
  • “Tests are too hard to maintain!”
  • “Junior devs don’t know how to write tests...”
  • “...and we don’t have bandwidth to train them.”
But it’s hard — Scott Pilgrim vs. the World.

Hard or not, we need to write tests

If our code isn’t tested, we’re just guessing

Even smaller codebases have lots of edge cases

Manual quality assurance doesn’t catch everything

Testing Doesn’t Have to Be Hard

A battle-tested strategy

  • Code changes must be sent as pull requests
  • A build pipeline runs tests automatically
  • The new code must meet testing requirements
  • The new code must meet quality guidelines
  • Change must be peer reviewed and approved

What should the testing requirements be?

  • The app builds successfully
  • All tests pass
  • Coverage thresholds must be met for new code
  • Coverage thresholds for the whole repo (maybe)

What should the quality guidelines be?

  • Limit cyclomatic and cognitive complexity
  • Avoid known problematic patterns
  • Check for security vulnerabilities
  • Eliminate duplicate code

We should not fail a pull request on style

Just use Prettier and forget about it.

Test and quality checks can be automated:

  • Linters and IDE plugins to help as code is written
  • Husky and Git hooks to check changes pre-push
  • TravisCI and Jenkins to build and test PRs
  • SonarCloud, Code Climate, Codacy for quality checks
  • Prettier to auto-fix code style

Why This Strategy Works

Pull requests create a control flow

  • No force pushing
  • Creates a place for automated tests to run
  • Requires team participation

Automated tests catch more edge cases before regressions happen

Quality checks minimize technical debt and maintenance overhead

Automating enforcement removes the need for a human code cop

Peer reviews create opportunities to learn
& share knowledge

Testable code is better code

  • Cleaner separation of different functionality
  • Fewer side effects (because mocking sucks)
  • Better APIs because edge cases are tested for

Okay, but...

How Do We Get There?

Make the Right Thing the Easy Thing

Integrate checks into your workflow

Code Climate GitHub integration.

Source: Code Climate

Use built-in coaching to improve quality

Codacy issue explanation.

Source: Codacy

Make the learning curve as shallow as possible

Using 3 packages for testing is confusing

Testing with Mocha + Chai + Sinon.

A unified API makes testing approachable

Testing with Jest.

Starting from 0% is hard

Keeping tested code tested is significantly less hard

Internal training is key

  • Hackathons to add tests to older code
  • Hands-on workshops to teach testing techniques
  • Cross-team code reviews to share knowledge
  • Compile best practices into internal docs
  • Coach the team on writing more testable code
  • Hire external trainers if necessary

Don’t forget: executives also need training

  • An untested product is fragile
  • Fragile products break in unpredictable ways
  • Unpredictability causes delays
  • Delays cost money and frustrate customers

Make code quality a point of pride

Visually represent code health in public

SonarQube dashboard.

Source: SonarQube

Measure code health over time for teams

Code quality over time on SonarQube.

Source: SonarQube

Make testing a deliverable not a “nice to have”

New features without tests are not safe to launch

What if people fight testing?

Change is hard:

  • Old habits are hard to break
  • New requirements cause anxiety

Replace old habits with better ones

Try to understand where resistance is coming from

Focus on the bright spots

Reward the right behavior

  • Use testing and quality as a metric during reviews
  • Publicly recognize team members who improve code

If that doesn’t work...

Reorganize resistant teams

Measure management on their team’s code quality

A word of caution:

Don’t add requirements without adjusting expectations. Deadlines will need to shift at first.

Stop rewarding bad behavior

Teams shipping features without tests missed their deadline

This is not okay:

“We just need to get something out there. We’ll add tests later.”

Be reasonable

Start plugging leaks first

Create a ramp-up period

Go slow to go fast

Improving foundational quality will help to:

  • Increase the reliability of code
  • Decrease the time to find and fix bugs
  • Speed up delivery times for new features
  • Eliminate existing technical debt...
  • ...and help prevent new debt from being created
  • Lower the cost of maintenance

RecapWith Action Steps

To create quality-driven culture in your company:

  1. Make the Right Thing the Easy Thing
  2. Provide support and ramp-up time for developers
  3. Convince management to make time for quality
  4. Reward the desired behavior...
  5. ...and stop rewarding bad behavior
  6. Automate as much of the process as possible
  7. Take pride in shipping quality, not just shipping
Don’t ship shit.

Credit: Vanessa Brooks

Testing is a supercharger for companies

It’s slow and difficult to get the mindset in place...
but then it’s unstoppable

Thanks!

Jason Lengstorf

Jason Lengstorf
@jlengstorf  ·  jason@lengstorf.com

Tweet: @jlengstorf #assertJS