Blog
Technical

Leveling up your test environments with OCI artifacts

Author
Trey Briccetti
February 8, 2024
Leveling up your test environments with OCI artifacts
In this article
    Share

    TL;DR: OCI artifacts have improved the way we manage testing environments by allowing us the ability to store, version, and distribute test data with docker registries.  Leveraging this technology to create isolated test environments with high quality data is easier than ever using Tonic’s Output to Repos feature.

    In a Tonic blog article from 2020, we discussed the benefits of using Docker to manage test databases and provided a template project to help you get started. Since its publication, "Using Docker to Manage Your Test Database(s)" has held steady as one of our most popular reads. Today, we wanted to share how we’ve updated our test data management solution to use OCI artifacts and bring even more benefits to the table.

    What is an OCI artifact?

    A once common exploit of the Docker Image was to embed arbitrary media into the layers of an image and then upload it to a registry, allowing the use of OCI registries for distribution of more than just containerized applications.  

    In a tale as old as time, the bug has become the feature - OCI Artifacts have entered the scene as an accepted way to distribute any type of media with OCI registries, enabling developers to keep all of their deployment goodies in one big bucket of joy.

    Helm charts, SBOMs, GitBoms, gifs of cats, and container images have all found their way into the OCI Registry, and we have been soaking up the benefits of having these highly available, compact, versioned pieces of our deployment puzzle.

    Recently, test data has joined the ranks and found its place in the OCI Registry, helping developers and pipelines around the world to have on-demand access to copies of data for testing.

    To help hammer the nail here on the importance of test data artifacts, I’ve created a very simple example of a full-stack application with a build and test script that employs them.

    All of the relevant code for this project can be found at https://github.com/bricct/contact-list.

    Working with an example

    An example application that represents a contact list comprising a few simple components: a React front end, a .NET API, and a PostgreSQL database.

    The example application here represents a contact list that comprises a few simple components: a React front end, a .NET API, and a PostgreSQL database.

    The database holds the contact information of 6 people, the API serves this data to the front end, and the frontend displays that information in a list.

    Clicking any of the “X” buttons will delete that contact from the list. The contact count on the page decreases by one each time a contact is deleted. To test the behavior of this feature, a Playwright test mimics user input.

    “Production” environment

    The build directory contains subdirectories for each type of the build environments that we want to emulate: one for “Production” and one for “Test."

    Running the build script in the prod folder runs the application locally and allows the user to see the production data in the contact list. We can click around here to test whether the behavior of the front end is what we would expect.

    A gif showing a few steps to test out the front end behavior of the example application.

    Clicking a delete button hides a contact from the list, and updates the count at the bottom.

    Test data as an artifact

    Imagine that we want to use CI to automatically test the behavior of the “contact list count” updating every time we click “delete contact”. It’s safe to say that any contact list information in an application contains PII, so it’s important that we don’t use production data for the tests.

    You might think that this forces us to carefully create our own test data by hand, or to connect to some internal test data server, but that is no longer the case. Using a recently released Tonic feature, we can create containerized database artifacts of test databases. These artifacts are stored in OCI registries, and can be pulled and mounted to database images when it is time to test the application.

    To take a look at how useful this is, lets docker-compose down the production environment and take a look at the build script for the test environment.

    “Test” environment

    Let’s look at our simple test automation script for the application:

    The oras pull command is downloading the test data artifact datavol.tar.gz which we untar and unzip to become the postgres data folder.

    To create the test environment, we:

    1. Build the API and front-end images
    2. Retrieve a test database artifact
    3. Compose the API, front-end, and PostgreSQL containers

    In the yaml for docker-compose, you can see that the folder that we are extracting from the test database artifact is mounted to the PostgreSQL container.

    After the docker-compose is finished, the front-end is pinged until it is online, and the Playwright test runs to validate the behavior we expect. Afterwards, the containers are torn down.

    Let’s run the script and see what happens:

    A screenshot of the script running.
    A screenshot of the front end showing Tonic generated test data in the UI.

    If we peek at the frontend while the test is running, we can see it is using tonic generated data.

    Just like that, our application is being built deployed and tested with highly available, safe, realistic test data in an isolated environment.

    The secret sauce: Tonic’s new output to repositories feature

    The Tonic Output to Repos feature allows us, with just a little configuration, to go from a production database full of sensitive data to a highly available test data artifact that is ready for test and development environments.

    A screenshot of the Output-to-Repos UI in the Tonic test data platform.

    The Tonic UI to configure Output to Repos

    Using our credentials for an OCI repository, we can configure the workspace to create a test data artifact from our production database. Then we can pull it as many times as we need from any machine that has credentials to pull from that repository—and voila! Everything test data everywhere all at once!

    Tonic’s output to repositories feature aims to make your life a little easier, so you can get back to the important things in life, like looking at gifs of cats. Curious to try it out for yourself? Sign up for a free trial of Tonic to get started.

    Sidenote: Oras

    Oras, or OCI Registry as Storage, is a client written in Go that, among other things, allows you to pull OCI artifacts directly to your machine via an oras pull command.

    Unfortunately, the Docker client does not yet support the ability to pull and push the arbitrary media types of an OCI Artifact, so we needed to use the oras client. Check them out here!

    Trey Briccetti
    Software Engineer
    As a software engineer at Tonic, Trey has helped develop core features such as Subsetting, Upsert, and Output to Repos. Currently he is helping to build Tonic’s newest product, Ephemeral, which launched earlier this month.