Table of Contents for
Test-Driven Development with Python, 2nd Edition

Version ebook / Retour

Cover image for bash Cookbook, 2nd Edition Test-Driven Development with Python, 2nd Edition by Harry J.W. Percival Published by O'Reilly Media, Inc., 2017
  1. Cover
  2. nav
  3. Praise for Test-Driven Development with Python
  4. Test-Driven Development with Python
  5. Test-Driven Development with Python
  6. Preface
  7. Prerequisites and Assumptions
  8. Companion Video
  9. Acknowledgments
  10. I. The Basics of TDD and Django
  11. 1. Getting Django Set Up Using a Functional Test
  12. 2. Extending Our Functional Test Using the unittest Module
  13. 3. Testing a Simple Home Page with Unit Tests
  14. 4. What Are We Doing with All These Tests? (And, Refactoring)
  15. 5. Saving User Input: Testing the Database
  16. 6. Improving Functional Tests: Ensuring Isolation and Removing Voodoo Sleeps
  17. 7. Working Incrementally
  18. II. Web Development Sine Qua Nons
  19. 8. Prettification: Layout and Styling, and What to Test About It
  20. 9. Testing Deployment Using a Staging Site
  21. 10. Getting to a Production-Ready Deployment
  22. 11. Automating Deployment with Fabric
  23. 12. Splitting Our Tests into Multiple Files, and a Generic Wait Helper
  24. 13. Validation at the Database Layer
  25. 14. A Simple Form
  26. 15. More Advanced Forms
  27. 16. Dipping Our Toes, Very Tentatively, into JavaScript
  28. 17. Deploying Our New Code
  29. III. More Advanced Topics in Testing
  30. 18. User Authentication, Spiking, and De-Spiking
  31. 19. Using Mocks to Test External Dependencies or Reduce Duplication
  32. 20. Test Fixtures and a Decorator for Explicit Waits
  33. 21. Server-Side Debugging
  34. 22. Finishing “My Lists”: Outside-In TDD
  35. 23. Test Isolation, and “Listening to Your Tests”
  36. 24. Continuous Integration (CI)
  37. 25. The Token Social Bit, the Page Pattern, and an Exercise for the Reader
  38. 26. Fast Tests, Slow Tests, and Hot Lava
  39. Obey the Testing Goat!
  40. A. PythonAnywhere
  41. B. Django Class-Based Views
  42. C. Provisioning with Ansible
  43. D. Testing Database Migrations
  44. E. Behaviour-Driven Development (BDD)
  45. F. Building a REST API: JSON, Ajax, and Mocking with JavaScript
  46. G. Django-Rest-Framework
  47. H. Cheat Sheet
  48. I. What to Do Next
  49. J. Source Code Examples
  50. Bibliography
  51. Index
  52. About the Author
  53. Colophon

Appendix H. Cheat Sheet

By popular demand, this “cheat sheet” is loosely based on the little recap/summary boxes from the end of each chapter. The idea is to provide a few reminders, and links to the chapters where you can find out more to jog your memory. I hope you find it useful!

Initial Project Setup

  • Start with a User Story and map it to a first functional test.

  • Pick a test framework—unittest is fine, and options like py.test, nose, or Green can also offer some advantages.

  • Run the functional test and see your first expected failure.

  • Pick a web framework such as Django, and find out how to run unit tests against it.

  • Create your first unit test to address the current FT failure, and see it fail.

  • Do your first commit to a VCS like Git.

Relevant chapters: Chapter 1, Chapter 2, Chapter 3

The Basic TDD Workflow

  • Double-loop TDD (Figure H-1)

  • Red, Green, Refactor

  • Triangulation

  • The scratchpad

  • “3 Strikes and Refactor”

  • “Working State to Working State”

  • “YAGNI”

A flowchart showing functional tests as the overall cycle, and unit tests helping to code
Figure H-1. The TDD process with functional and unit tests

Relevant chapters: Chapter 4, Chapter 5, Chapter 7

Moving Beyond Dev-Only Testing

  • Start system testing early. Ensure your components work together: web server, static content, database.

  • Build a staging environment to match your production environment, and run your FT suite against it.

  • Automate your staging and production environments:

    • PaaS vs. VPS

    • Fabric

    • Configuration management (Chef, Puppet, Salt, Ansible)

    • Vagrant

  • Think through deployment pain points: the database, static files, dependencies, how to customise settings, and so on.

  • Build a CI server as soon as possible, so that you don’t have to rely on self-discipline to see the tests run.

Relevant chapters: Chapter 9, Chapter 11, Chapter 24, Appendix C

General Testing Best Practices

  • Each test should test one thing.

  • One test file per application code source file.

  • Consider at least a placeholder test for every function and class, no matter how simple.

  • “Don’t test constants”.

  • Try to test behaviour rather than implementation.

  • Try to think beyond the charmed path through the code, and think through edge cases and error cases.

Relevant chapters: Chapter 4, Chapter 13, Chapter 14

Selenium/Functional Testing Best Practices

  • Use explicit rather than implicit waits, and the interaction/wait pattern.

  • Avoid duplication of test code—helper methods in a base class and the Page pattern are possible solutions.

  • Avoid double-testing functionality. If you have a test that covers a time-consuming process (e.g., login), consider ways of skipping it in other tests (but be aware of unexpected interactions between seemingly unrelated bits of functionality).

  • Look into BDD tools as another way of structuring your FTs.

Relevant chapters: Chapter 21, Chapter 24, Chapter 25

Outside-In, Test Isolation Versus Integrated Tests, and Mocking

Remember the reasons we write tests in the first place:

  • To ensure correctness and prevent regressions

  • To help us to write clean, maintainable code

  • To enable a fast, productive workflow

And with those objectives in mind, think of different types of tests, and the trade-offs between them:

Functional tests
  • Provide the best guarantee that your application really works correctly, from the point of view of the user

  • But: it’s a slower feedback cycle

  • And they don’t necessarily help you write clean code

Integrated tests (reliant on, for example, the ORM or the Django Test Client)
  • Are quick to write

  • Are easy to understand

  • Will warn you of any integration issues

  • But: may not always drive good design (that’s up to you!)

  • And are usually slower than isolated tests

Isolated (“mocky”) tests
  • Involve the most hard work

  • Can be harder to read and understand

  • But: are the best ones for guiding you towards better design

  • And run the fastest

If you do find yourself writing tests with lots of mocks, and they feel painful, remember “listen to your tests”—ugly, mocky tests may be trying to tell you that your code could be simplified.

Relevant chapters: Chapter 22, Chapter 23, Chapter 26