In the first chapter of this book, you about learned the history and philosophy of Python. Subsequent chapters explored the features of various test automation frameworks in Python. The frameworks you explored included doctest, unittest, nose, nose2, and pytest. Later, you learned about Selenium and logging in detail. This chapter looks at coding conventions that will make the test discovery easier across these frameworks. Then, you will look at the concept of test-driven development and learn how it can be implemented in Python 3 projects with the help of pytest.
Coding and Filenaming Conventions for Easier Test Discovery
You have seen that all the xUnit-style frameworks include test discovery, that is, the automated detection, execution, and report generation of tests. This is a very important feature, as it makes life easier for code testers. You can even schedule the test discovery process using OS schedulers (for example, cron in Linux-based operating systems and Windows Scheduler in Windows), and they will automatically run tests at scheduled times.
The names of all the test modules (the test files) should start with test_
The names of all the test functions should start with test_
The names of all the test classes should start with Test
The names of all the test methods should start with test_
Group all the tests into test classes and packages
All the packages with test code should have an init.py file
It is always a good idea to follow the PEP 8 convention for the code. It can be found at https://www.python.org/dev/peps/pep-0008/.
If you use these conventions for your code and filenames, the test discovery feature of all the test automation frameworks—including unittest, nose, nose2, and pytest—will detect the tests without any problem. So, the next time you write your tests, follow these conventions for best results.
You can read more about xUnit at https://www.martinfowler.com/bliki/Xunit.html and http://xunitpatterns.com/
Test-Driven Development with pytest
Test-driven development (TDD) is a paradigm whereby you implement a new feature or requirement by writing tests first, watch them fail, and then write the code to make the failed tests pass. Once the basic skeleton is implemented this way, you then build on this by altering the tests and changing the development code to accommodate the added functionality. You repeat this process as many times as needed to accommodate all new requirements.
Essentially, TDD is a cycle where you write the tests first, watch them fail, implement the required features, and repeat this process until the new features are added to the existing code.
By writing the automated tests before the development code, it forces you to think about the problem at hand first. As you start to build your tests, you have to think about the way you write the development code that must pass the already-written automated tests in order to be accepted.
To see how TDD is implemented in Python with pytest, create a directory called chapter08 for this TDD in the code directory. You will use this directory for the TDD exercise.
test_module01.py
calculator.py
test_module01.py
calculator.py
test_module01.py
The modified code shown in Listing 8-5 is trying to add an integer and a string, which should raise a ValueError exception.
calculator.py
test_module01.py
This is how TDD is implemented in real-life projects. You write a failing test first, refactor the development code, and continue with the same process until the test passes. When you want to add a new feature, you repeat this process to implement it.
Conclusion
In this chapter, you learned the coding and filename conventions for easy test discovery; these conventions can be implemented across all the automation frameworks. You also read a brief introduction to TDD.
This book began with an introduction to Python, including how to install it on the various OSs and the differences between Python versions 2 and version 3. Subsequent chapters explored the most commonly used test automation frameworks for Python.
Chapter 2 explored docstrings and explained how they are useful in writing doctests.
You learned that the doctest is not a very powerful test framework, as it lacks many essentials of a true test framework.
In Chapter 3, you were introduced to Python's batteries-included test automation framework, unittest. You learned how to write xUnit-style test cases for Python with unittest.
In Chapter 4, you explored a more advanced, but defunct, test automation framework called nose. You learned about the advanced features and plugins offered by nose. Because nose is not under active development, the chapter used nose2 as a test-runner for running nose and unittest tests.
In Chapter 5, you studied and explored one of the best unit test automation frameworks for Python, pytest. You learned how and why it is better than unittest and nose. You also explored its plugins and modular fixtures.
In Chapter 6, you studied and explored the Selenium browser automation framework, which is very useful in automating test cases for various web-related programming using web browsers.
Chapter 7 explored logging with logger and loguru. Logging is a very useful feature for developers and testers.
You have practiced numerous examples throughout the book, the goal of which is to instill you with confidence in Python test automation. You also learned to work with codebases where they have implemented test automation with unittest, doctest, or nose and plan a migration to pytest. You can now write your own routines and use logging to log the errors. You can also automate web-related test cases. Also, if you are a career Python developer or an automation expert, you can follow the TDD approach in your projects. I hope you have enjoyed reading this book as much as I enjoyed writing it. Happy Pythoning and testing!!