Writing Tests
Written on
Software without tests is broken by design.
Software without tests makes it hard to improve existing code and developers of untested applications tend to become pretty paranoid. If an application has automated tests, you can safely make changes and instantly know if anything breaks.—from Flask, Good practices
How Do I Start?
- Know the theory (testing levels, testing types, mocking)
- Think in terms of: “Cover highest risk” (e.g. main feature must work => acceptance, unit, security, performance … test?)
- Watch yourself: What would you (or do you) do to verify the code you’ve just written or modified?
- Refactor your tests:
- Mock away external dependencies (code that isn’t part of your codebase)
- Replace your slowest test with (several) faster tests
- Reorganize your code to allow you to remove mocks
1. Acceptance Tests, Feature Tests (Behave)
Specify tests in Gherkin language, implement them in Python. Provides a “common language” for all project members, across all project levels.
- Behave (tutorial, examples), pytest-bdd (examples)
- Gherkin language plugin for JIRA (specify tests, download as
.feature
files) - Many editors support Gherkin language (PyCharm, Sublime via BehaveToolkit)
2. Front-end Tests (Selenium)
Automate interactive browser testing, mimicking user interaction on live sites (and apps).
- Selenium (WebDriver API, Django Selenium testing, code samples: BrowserStack, Testing Bot)
- GhostInspector (Chrome plugin)
- Appium (Selenium for iOS and Android)
- behaving (= behave + Appium + splinter)
- Visual Testing
Tests using those frameworks can be run by any test runner (e.g. pytest, behave, etc.).
3. Unit Tests (Python)
Safeguard functional units (modules, packages, “backend”) against regression.
- Python-Guide on writing tests (nice overview of frameworks)
- Testing with Django (intro, overview) – the Django tutorial uses
unittest
instead ofpytest
, hence tests are a bit more verbose (“boilerplate” code) - pytest (examples)
- pytest-django (tutorial)
General Recommendations
Selenium
- Use page objects! – Write your tests against an API of your pages, not against the HTML. (why?)
Django
- Don’t mock the DB / your model! – Refactor your code, so most of the code doesn’t need to talk to the DB. (why?)
- Don’t use fixtures for test data! – Use model factories instead. (why?)
- Write less view code! – Testing views is hard. Use RequestFactory or write BDD tests. (why?)
- One action per test method, no multi-step tests! – A failing test method must tell you what’s broken. (why?)
- Best Practices for Visual Testing (huxley)
See Also
External Resources
- Lessons on Testing by David Cramer (video - write testable code)
- Integration and Functional Testing with LiveServerTestCase, Selenium (video)
- Django Testing Tips (video)
- Test Driven Development for Small Django Projects (video - settings, factory boy)
- Obey the Testing Goat! (TDD introduction, book, and video series by Harry Percival)
- Writing tests in PyCharm (helpful screencast for PyCharm users)
comments powered by Disqus