Apr 18, 20228 min read
Dawid Karczewski
Senior full stack developer and CTO at Ideamotive.
The contemporary environment of software development is diverse enough to have different approaches to coding. The oldest and the most conventional one is an architecture-driven method. This is when an application is completed with all desired features, and tests are run afterward. A “test-last” concept lies in the background of such a development method, therefore.
The approach originates in the days when agile development has not been widely adopted yet. The biggest disadvantage of the method is that the whole team has to check the entire code base for hours or even days to fix just a single line of code when one of the tests fails.
A decent alternative to the architecture-driven approach is test-driven development (TDD). The method appeared in 1999 under a “test-first” concept that was an element of extreme programming (XP). Later on, TDD became a standalone methodology, however.
Test-driven development offers a sequence of actions that is reverse to architecture-driven programming: tests for every code unit are created prior to the very code appearing. It may sound irrational and time-consuming at first glance. The final effect, however, is the opposite: only clean code is delivered to production with no redundant time spent on bug fixing.
Is test-driven development relevant to every project? Can the approach be applied to programming in Python? Where to find Python developers who possess hands-on TDD? The present post aims at answering the questions as well as delivering some fundamentals about test-driven development.
TDD is a software development technique based on very short recurrent cycles consisting of the following three stages:
One of the critical aspects of test-driven development is that programmers have to create tests on their own without assigning testers. The teams staying far from TDD may argue that this is not a programmer’s business to write tests. It is valid for the traditional test-last approach when tests are run post factum after a particular development stage is finished. As a result, the following typical drawbacks of the test-last method take place:
Test-driven developers think otherwise: there should be a test for every given module before a programmer writes code for it. Nobody but programmers have to create those module tests, therefore. Moreover, the first test always fails since no code is still available. Why so? It is worth grasping a typical TDD cycle in more detail.
TDD adherents divide a development cycle into three stages with several steps in each. The first “red” stage consists of the following:
Step 1: consider a code module to be written for a particular function;
Step 2: write a module test;
Step 3: run the test that will inevitably fail.
Some developers call step 2 “writing a failing test” not for nothing: there is no code capable of passing the test. “Any test deserves no trust unless it fails at least once,” they say. This is some sort of self-motivation when a failed test encourages developers to consider either the functional correctness of the future code or the test as such.
The second “green” stage includes the following:
Step 4: write a minimum possible code to pass the test. If the test goes green, the functionality of the code is correct. It is critical to make the code pass the test once and fail the test once. Making mistakes is easy: the always-passing tests, as well as always-failing ones, imply nothing special to create. But the test that can be as passed as failed definitely checks some kind of logic.
Step 5: Run the test again to make sure that the code’s functionality works well.
The last “refactor” stage of test-driven development implies writing clean code with no redundant elements and repeating steps from 1 to 5. The shorter the whole cycle, the better.
Even though test-driven development can hardly be a universal approach applicable to every project, some apparent benefits of TDD cover a wide variety of development practices. The following ones can optimize the programming workflow, to name a few:
When a company hires Python programmers unfamiliar with test-driven development, some sort of opposition may arise due to biases and misconceptions that circulate among the developers. A lack of knowledge about the test-driven approach lies in the background of those misconceptions. Even though they may sound strongly logical, there are enough counter-arguments to debunk any wrong vision of test-driven development.
Misconception 1: TDD is all about testing and test automation.
Clarification: TDD is a programming methodology based on the “test-first” approach.
Misconception 2: TDD implies no designing.
Clarification: TDD includes critical analysis and design in accordance with technical requirements.
Misconception 3: TDD works at the level of a single code module.
Clarification: There are no constraints to using TDD at both the integration and system levels.
Misconception 4: TDD does not work in projects with traditional testing cycles.
Clarification: TDD is popular in extreme programming and other kinds of agile development. At the same time, nothing prevents TDD from being applied to the development stage of any traditional project in addition to its post-development testing stage.
Misconception 5: TDD is just a tool.
Clarification: TDD is a methodology when each new module test is to be added to the automation test suit. All the tests have to be run after any change in the existing code as well as after each refactoring. Hence, various means of test automation facilitate TDD, which is more than just a tool.
Misconception 6: TDD implies transferring the acceptance tests from testers to developers.
Clarification: TDD does not exchange testers for developers in acceptance tests since a set of specific development-centric tests such as unit and module tests are run by programmers at the development stage.
Test-driven development can be accepted as a methodology by Python programmers when their project meets particular conditions. Some of them belong to external conditions, and some others do to internal ones. Thus, the choice depends on the following factors:
The following criteria seem to be helpful to recognize the cases when TDD is worth doing:
Test-driven development is not a panacea as we see. If TDD does not fit your project, the development process is getting slower, and programmers tend to come to the wrong generalizations such as:
To avoid such grim hesitations, it is worth assessing TDD from the perspective of your development activity. Test-driven development is hardly recommended if:
To use or not to use TDD is an individual issue. A lot depends on the project, the development team leaders, and the corporate values you have. TDD provides no breakdown of patterns if the following basic principles are kept in mind:
Whether Python is an appropriate technology for test-driven development seems to be an idle question, as many Python programming engineers believe. The very availability of relevant automation test suites and frameworks determines how well one or another technology can work in TDD. Python, in such a context, is one of a few programming languages that are rich enough with tools for modern testing practices.
Python is famous for its simple readability and ease of coding. Python automation engineers do not need to use compilers for converting code since the language is scripting. The “Zen of Python” automation guide claims that tests implemented via a test suite are easily readable and explainable.
Selenium automation framework, for example, allows using web browsers to create automated tests with elegant simplicity. Automation test scripts appear through the interaction of Selenium WebDrive with such browsers as Mozilla Firefox, Google Chrome, Internet Explorer, Safari, and Opera. The tool is compatible with Python and other scripting languages to create fast repeated tests in continuous integration pipelines.
Another Python-centric automation test framework is Robot. The framework allows developers to write code when a failing test is available only. A more explicit feature of test-driven development can hardly be found. Robot is written in Python and aimed at organizations that practice Agile development and TDD.
Many Python developers consider PyTest the best automation test framework ever. Unit tests, end-to-end tests, and integration tests all are easily implementable with the framework. Only a few Python programmers seem to prefer the by-default test suite PyUnit (unittest) instead of PyTest since the latter has a much wider scope of testing options.
In addition to the testing frameworks, some dedicated Python libraries suitable for TDD are also available. Hypothesis, for example, is the one that helps create more powerful and simpler-to-write unit tests capable of finding poor code where it can hardly be expected. The library is seamlessly compatible with any test suite.
As we see, Python is rich with testing toolkits that make test-driven development a highly appropriate approach to almost any software written in Python.
Answering the question “why you should use test-driven development” has several possible variants. First of all, TDD is about the uncompromised quality of code refined due to numerous refactoring. Debugging happens organically over the entire development life cycle.
Another aspect is time (and, therefore, money) saved due to a shorter pre-deployment acceptance testing. Much more elegant code appears in less time when progressive agile approaches, such as test-driven development, are practiced along with continuous integration/continuous delivery.
Few other technologies are more compatible with TDD than Python: various automated test tools are sufficiently available for the language. Test-driven development with Python is a formula of success for the customers who follow the zeitgeist.
Contact us today if you share our vision of the perfect “TDD + Python” combination capable of meeting the requirements of any software project. Top-notch development services and dedicated teams of professional Python programmers are always available for reasonable pricing.
Dawid is a full stack developer experienced in creating Ruby on Rails and React Native apps from naught to implementation. Technological superhero, delivering amazing solutions for our clients and helping them grow.
View all author postsTrending articles
21 Dazzling Examples of Mobile App UI Design to Inspire You in 2023
Michał Pruciak 7 min read
MedTech vs HealthTech vs BioTech: What Are The Differences?
Michał Pruciak 7 min read
10 Business Applications of Neural Network (With Examples!)
Michał Pruciak 4 min read
10 Irresistible Examples of Web Design Best Practices for 2023
Adam Kozłowski 7 min read
28 Amazing Examples Of PHP Web Development
Dawid Karczewski 14 min read
Looking for a specific type of software development service?
There are dozens of vetted Python professionals in our talent network.
Business registry data:
Company
Services
Most desired experts
Rated 4.8 / 5.0 by clients from various industries and locations.