Agile, test-driven development
It All Started with a Test
![](/var/linux_magazin/storage/images/linux-magazine.com/issues/2013/154/perl-test-driven-development/schilli_michael_5.png/590828-1-eng-US/Schilli_Michael_5.png_medium.png)
Test-driven development with a full-coverage regression test suite as a useful side effect promises code with fewer errors. Mike "Perlmeister" Schilli enters the same path of agility and encounters a really useful new CPAN module.
A few weeks ago, my employer sent me to a course about test-driven development (TDD) and agile methods, and to implement my newly gained knowledge practically, I am dedicating today's Perl snapshot to this principle.
Fast and flexible developers typically set off immediately without paying attention to details. They always write a test first before they get down to implementing a function. The test suite thus grows automatically with tests relevant to system functions. They clean up dirty code by refactoring later; this is possible without any risk thanks to the safety net provided by the test suite.
Nothing but Errors – and Rightly So
The tests developed before writing a function will fail, of course, because the desired feature either does not exist or is only partially or incorrectly implemented at first. When the code arrives later on, the test suite passes and turns to green; development environments such as Eclipse actually visualize it this way.
For example, to write a User.pm
class for a login system that later supports methods such as login()
, TDD disciples first create a test case. It checks whether the desired class can actually be instantiated. Listing 1 shows the test file for simple test cases, Basic.pm
. It is located in the directory t
and uses the brand new CPAN Test::Class::Moose module from CPAN. The latter runs all methods with the test_
prefix and the test utility routines they invoke.
Listing 1
Basic.pm
Listing 1 [1] defines test_constructor()
and runs the command
can_ok 'User', 'new';
from the Test::More module in it. Thus, test_constructor()
verifies whether the User
class is capable of calling its constructor new
.
Listing 2 shows a script for running the test suite. At first, it draws in the Load
module, which loads all Perl modules with the .pm
suffix that exist in the specified subdirectories (.
and t
). The runtests()
method then executes all test_*
routines found in these modules. In this phase of the project, the User
class does not yet exist, and the test case in test_constructor()
thus fails (Figure 1).
Listing 2
runtests
A Sense of Achievement
The test-driven developer naturally expected this outcome and now does everything possible to add code until the test suite completes without error. Because the class does not exist, the developer creates a new User.pm
file and then adds the following content:
package User; use Moose; 1;
Old hands like your very own Perlmeister might rub their eyes in disbelief at this, because the User
package does not define a new()
constructor that welds an object hash $self
onto a package using bless()
. The Moose [2] CPAN module does all of this behind the scenes, so every packet that Moose looks at automatically owns a new()
constructor.
A new run of the test suite using ./runtests
returns these promising results:
<[...]> ok 1 - TestsFor::User
The suite therefore finds the new .pm
file, the class it contains, and the new()
constructor.
Once More into the Agile Fray
Green light – the signal for TDD developers to add a new feature. The User
object needs methods to set and query the user's email address. A developer working conventionally would probably immediately start typing the seemingly simple code. Not so TDD followers; they first write a test that again fails.
Listing 3 defines the test_accessors()
method, which the test module later also finds and calls due to the prefix. It creates a new object of the User
type and passes the parameter pair email => 'a@b.com'
to the constructor. One line later, the erstwhile undefined accessor retrieves the email string set by the constructor, and the is
function from the Test::More module compares the value with the one set previously. If the contents match, is
writes the ok
string to the TAP output of the test suite. The suite will recognize this as a successfully executed test case.
Listing 3
Accessors.pm
This test is followed by a test of the setter, which uses the email()
method to set a new value for the user's email address and then runs the accessor (also email()
but without an argument) to retrieve the stored value again and compare it with the original. But the User.pm
class still does not have the necessary code; the new test therefore fails immediately.
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
![Learn More](https://www.linux-magazine.com/var/linux_magazin/storage/images/media/linux-magazine-eng-us/images/misc/learn-more/834592-1-eng-US/Learn-More_medium.png)
News
-
NVIDIA Released Driver for Upcoming NVIDIA 560 GPU for Linux
Not only has NVIDIA released the driver for its upcoming CPU series, it's the first release that defaults to using open-source GPU kernel modules.
-
OpenMandriva Lx 24.07 Released
If you’re into rolling release Linux distributions, OpenMandriva ROME has a new snapshot with a new kernel.
-
Kernel 6.10 Available for General Usage
Linus Torvalds has released the 6.10 kernel and it includes significant performance increases for Intel Core hybrid systems and more.
-
TUXEDO Computers Releases InfinityBook Pro 14 Gen9 Laptop
Sporting either AMD or Intel CPUs, the TUXEDO InfinityBook Pro 14 is an extremely compact, lightweight, sturdy powerhouse.
-
Google Extends Support for Linux Kernels Used for Android
Because the LTS Linux kernel releases are so important to Android, Google has decided to extend the support period beyond that offered by the kernel development team.
-
Linux Mint 22 Stable Delayed
If you're anxious about getting your hands on the stable release of Linux Mint 22, it looks as if you're going to have to wait a bit longer.
-
Nitrux 3.5.1 Available for Install
The latest version of the immutable, systemd-free distribution includes an updated kernel and NVIDIA driver.
-
Debian 12.6 Released with Plenty of Bug Fixes and Updates
The sixth update to Debian "Bookworm" is all about security mitigations and making adjustments for some "serious problems."
-
Canonical Offers 12-Year LTS for Open Source Docker Images
Canonical is expanding its LTS offering to reach beyond the DEB packages with a new distro-less Docker image.
-
Plasma Desktop 6.1 Released with Several Enhancements
If you're a fan of Plasma Desktop, you should be excited about this new point release.