The smarter not harder mindset is also essential for writing good automated software tests by Luke Plant

Introduction

The smarter not harder mindset is also essential for writing good automated software tests.

It’s in this context that religious devotion to things like TDD can be really unhelpful.

For many religions, the more painful an activity, and the more you do it, the more meritorious it is — and it may even atone for past misdeeds.

If you take that mindset with you into writing tests, you will do a rather bad job.

“Test smarter, not harder” means:

  • Only write necessary tests — specifically, tests whose estimated value is greater than their estimated cost. This is a hard judgement call, of course, but it does mean that at least some of the time you should be saying “it’s not worth it”.

  • Write your test code with the functions/methods/classes you wish existed, not the ones you’ve been given. For example, don’t write this:

    self.driver.get(self.live_server_url + reverse("contact_form"))
    self.driver.find_element_by_css_selector('#id_email').send_keys('my@email.com')
    self.driver.find_element_by_css_selector('#id_message').send_keys('Hello')
    self.driver.find_element_by_css_selector('input[type=submit]').click()
    WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element_by_css_selector('body'))
    
    That looks very tedious! Write this instead::
    
        self.get_url("contact_form")
        self.fill({'#id_email': 'my@email.com',
                   '#id_message': 'Hello'})
        self.submit('input[type=submit]')
    
    (Like you can with django-functest, but it’s the principle, not the
    library, that’s important.
    
    If the API you want to use doesn’t exist yet, you still use it, and
    then make it exist.)
    

Don’t write tests for things that can be more effectively tested in other ways, and lean on other correctness methodologies as much as possible.

These include:

  • code review

  • static type checking (especially in languages with sound and powerful type systems, with type inference everywhere, giving you a very good cost-benefit ratio)

  • linters like flake8

  • formal methods

  • introspection (like Django’s checks framework)

  • property based testing like hypothesis.