Skip to content
Bytes by Ying
Go back

Data-driven Testing with 'pytest', Part Four: Fungible Infrastructure

Edit page

My previous post discussed how an update to a testing schema opened the test harness to better capture the rest of the statefulness of the ETL pipeline. This post discusses how the infrastructure setup in the test harness evolved to capture the statefulness of each resource dependency.


SSL: Where it all began

The test harness worked quite well after the prior update, and I was able to migrate the remaining test cases to the new framework and delete the old test harnesses entirely. Then one day, one customer asked for SSL support, because they hosted all of their credentials on their own LDAP server and wanted a secure channel for authentication. A very reasonable ask, as credentials should not be passed as plain-text over network, all our services already supported SSL connections, and I didn’t have SSL support in the tool. I thought it would take a few days.

It ended up taking a few weeks when interspersed with other feature development. The difficulty arose when attempting to set the configuration in a reproducible manner. There’s quite a few knobs to turn, and tuning them incorrectly results in the database being in an erroneous state. Getting the database out of the erroneous state took time too, as I did not back up my configuration files and hence had no automated rollbacks. I ended up throwing the updated feature (with maybe a dozen lines of code changed total) over the wall to a colleague, who verified it and sent it to the customer. After that, I really wanted fungible third-party dependencies.


Difficulties with Existing Infrastructure

In the beginning, I had all my third-party dependencies (such as all the databases) installed on bare metal. This resulted in a not-insignificant amount of friction (in addition to the ones already described):

The takeaway from all this is to have good enough test infrastructure that can effectively absorb or mitigate these risks to development velocity.


Solution: Containerization

Taking yet another page from our QA team, which had good experiences with Docker and containerizing our database for testing purposes, I decided to use Docker and bash to script the database setup with SSL enabled, and tried to make the infrastructure setup as simple as possible. It was also a great opportunity to learn more about Docker and how containerization worked.

Containerization itself was not too difficult. As our database ships as a monothlic RPM, it was easy to create a Dockerfile based on top of the maintained 'centos' Docker image, docker cp over the RPM to the container, and run yum install -y $RPM to deploy the database. The difficult SSL configuration, which blocked me from finishing the infrastructure for a few more weeks, was resolved with the help of a sales engineer who had already wrote a number of bash scripts to address this problem. It was literally a Hail Mary in terms of discovery and efficacy, and this post wouldn’t be possible without his work :sweat_smile:

Here’s some of the other, more interesting gotchas/hacks I encountered/implemented:


Lessons Learned

I’m still very much a newbie at Docker and containerization (My test infrastructure is one container on one machine and likely will be for a while, so no docker-compose or Kubernetes or anything), but there’s some things I really appreciate about going through this process:


Conclusion

Infrastructure setup was the keystone in a long journey to automating testing for this project. Now in pull requests, I can say to the code reviewer on pull requests to check out this branch, build the distribution, and execute this one script in order to run all the tests, instead of digging all the way down into site-packages to find the tests and run them as a one-step process. Much simpler to understand and get started with, with corresponding benefits to onboarding and test coverage. With the requirements I have on my roadmap, it will be a while until I encounter a problem that can’t be tested with the existing design abstracted implemented so far (e.g. an updated test case schema and test harness, another Docker container, etc).


Thanks for reading this four-part series! I hope you found it as informative as I found it a joy to write.


Edit page
Share this post on:

Previous Post
Gestalt-driven Software Development
Next Post
Data-driven Testing with 'pytest', Part Three: Chained Operations