Wondering how unit testing transcribes to the DevOps culture? In this two-part article, we continue reviewing the topic that we started in the first part .
Unit Tests Are Built-In Regression Tests
When introducing new functionality, one of the biggest costs of manual testing (in time and dollars) is making sure that existing functionality isn’t broken. That’s also one of the biggest risks of introducing changes. I’ve written about this kind of problem before with respect to legacy code. Basically, no one wants to make changes because the risks and costs are too high.
Since technology changes so rapidly, this puts your business in a precarious position. On the one hand, the cost of change is too high to take action. On the other, the price of stagnation could mount to a total loss as more agile competition edges you out. Luckily, unit testing has regression testing built right in to make sure that previous deployments still work when combined with new functionalities.
Think of unit testing as just another form of automation. DevOps culture seeks efficiency through automation. Regression testing is prime for automation! The process is repeatable. It’s predictable. We can quantify an expected outcome. With the right knowledge and tooling, it’s easier than you may think. Once you have unit tests and other types of automated tests performing regression testing rather than humans, the QA team is freed up to focus more on testing the new functionality.
You Can Apply Unit Testing to the Operations Code
Although we don’t have access to write unit tests for many of the underlying platforms, with a little creativity, we can write unit tests for the operations scripts. The following example shows how you can test functions that are used in your scripts:
# a unit test of a getVersionTag function
# TAGS is a list of tags from a commit, one of which is the version tag
TAGS := [ "version-1.0.1", "hello-tag", "bob-was-here" ]
# should fish out the version tag from the list of tags
deploymentVersion := getVersionTag(TAGS)
if ( deploymentVersion != "version-1.0.1" ) then "fail"
else "pass" endif
The script above shows a unit test for the fictitious “getVersionTag” function. The function takes in an array of tags and returns the one containing the version. The script performs a verification at the end (labeled “assert”). Now you can use the “getVersionTag” in an actual deployment script and be assured that it will get the tag containing the version.
You Can Also Automate Tests to Validate Deployment
Not only can we unit test the scripts, but we can also write integration tests to validate deployment.
Let’s say, for example, you have a deployment process that rolls the latest version of your web app out to some servers. Wouldn’t it be great to have some tests run automatically to verify that those servers do indeed have the latest version of the app deployed? To check if the Ops code did what you expected? There’s no rule that says you can’t do that. In fact, if you’re really into practicing DevOps, you probably already have this kind of automated test as part of your deployment process.
But let me be clear: this isn’t unit testing. Unit testing is about testing a single piece of functionality in isolation. Unit tests should execute as quickly as possible, so they can and will be run often. Still, this example might give you a good idea about the possibilities of automating your testing. If you can imagine testing operations code, you can surely imagine unit testing application code.
We’ve seen where unit testing fits in with DevOps and where it doesn’t. All in all, if you’re practicing DevOps, you are likely to see a benefit from unit testing. DevOps is about making the delivery of software more efficient. This reduces costs, which increases margins. Unit testing also shortens the lead time for fixing bugs and adding new features. It enables software to be softer, or more changeable, by reducing the risk of change. Because of its focus on quality and automation, unit testing fits right in near the core of DevOps. You should have unit testing embedded deeply within your DevOps culture.
Read the 1st part here.