Integrations tests in CircleCI

Read how to run Cypress and other integrations tests in CircleCI, to make sure that your code was still working fine after a change.
June 22, 2021
Jira
Microsoft Teams
Technology

Recently I worked on setting up integration tests on our CircleCI CI/CD pipeline for Microsoft Teams Jira Connector Server and Data Center plugins.
Our product is a Java application that integrates Jira with Microsoft Teams to provide enhanced visibility in Microsoft Teams on projects in Jira.
In this article I’ll share how I did it.

TL; DR

If you are just interested in the specific technical details, here are the steps I followed:

  1. Create a Docker image that uses the CMD instruction to run atlas-run-standalone.
    Docker file should look something like this:

FROM alpine

# Download Atlassian SDK...

CMD atlas-run-standalone --product jira --http-port 2990 --server 0.0.0.0 --jvmargs -Xmx4096M -DskipAllPrompts=true


2. Or you can use our alpine image.

Add that image as a secondary container in CircleCI config file:

docker:

- image: circleci/openjdk:8-jdk # Main image

- image: moveworkforward/atlas-run-standalone:jira-alpine # Secondary image

Build your Java application and run atlas-install-plugin to install it.

Wait for Atlassian application to be up and running and then run your integration tests.

What we tried to achieve

Although we had unit tests for both back-end and front-end, we did not have end to end tests running on our CI/CD pipeline.
We had integration tests but we had only been running them locally on each developer’s machine.
Our goal was to run Cypress and other integrations tests in CircleCI, to make sure that our code was still working fine after a change.

First attempt - Single container and atlas-run

First thing I tried was to run Atlassian Plugin SDK shell script atlas-run in the same way we run it locally in our machines and using just a single container.
CircleCI has the option to run steps in the background. When it’s set to true Job execution will immediately proceed to the next step rather than waiting for return of a command. That way you can leave servers running for example, while also executing the following steps.

- run:

   name: Atlas Run

   command: atlas-run

   background: true

Unfortunately that didn't work. The application would start and then just stop right away without any error message.

So when the steps that had to run the tests were executed, the application was not longer running.

After contacting CircleCI support they mentioned it could be related to memory issues.

CircleCI has a resource_class feature that allows configuring CPU and RAM resources for each job.
At the time of writing this article, they offer the following options for running docker containers:

So I tried increasing the amount of RAM memory used by the container but that didn’t make any difference. Even with 16GB, which should be more than enough, the application would stop.

I also checked some of their articles related to Java Memory Errors but that didn’t help either.

Since I couldn’t see any error message, I needed a way to get more information about what was happening with that step.
CircleCI gives you the option to debug all your jobs with SSH. That way you can inspect things like log files, running processes, and directory paths.
I used it to try to run the application and check if I could get any useful information when it stopped.
Surprisingly, the application executed correctly while debugging with SSH. I could even SSH from another terminal and run the integration tests without any issue.
That made me think that maybe memory was not the real issue, so I decided to try something else.

Second attempt - Multiple containers and atlas-run-standalone

My second approach was to use another Atlassian script, atlas-run-standalone, which runs an Atlassian application standalone, without a plugin project. Also, I’d try to run it in a different docker container.

CircleCI gives you the option to specify multiple Docker images for your job.
The container created by the first image listed act as the primary container in which all steps are executed and you can use the other containers as services.
It works in a similar way as docker-compose, so all containers run in a common network and every exposed port will be available on localhost from a primary container.
You can use it to run different services like a Database, a shared cache like Redis, a message broker or any other software you need to run as a service.

Since I couldn’t find any official image for my secondary container that did exactly what I needed, I decided to create one.
I built moveworkforward/atlas-run-standalone. It’s based on Docker alpine and I installed Atlassian Plugin SDK and added atlas-run-standalone command.
Dockerfile looks something like this:

FROM alpine

# Download Atlassian SDK...

CMD atlas-run-standalone --product jira --http-port 2990 --server 0.0.0.0 --jvmargs -Xmx4096M -DskipAllPrompts=true

Then we needed a way to tell CircleCI to wait until our Atlassian application was up and running.
For that you can use tools like dockerize but I decided that curl and a simple bash script would do the trick. This is how that step looks like:

- run:

   name: Wait for Jira

   command: |

     until $(curl --output /dev/null --silent --head --fail http://localhost:2990/jira);

       do

         printf '.'

           sleep 5

       done;

Once the application is running, we have to build our plugin and install it.

- run:
   name: Build backend
   command: atlas-package
   
- run:
   name: Install Jira plugin
   command: atlas-install-plugin --username username --password password --plugin-key com.your.plugin.key

You could also run your jobs in parallel with workflows to decrease your build times, which means building your application as a different job.

After all those steps finish successfully, we are ready to run our Cypress tests:

- run:
   name: Cypress tests
   command: npx cypress run

Depending on which image you choose as your primary container, you might need to install Cypress first.

If your tests start running and stop suddenly, you might be hitting your RAM memory limit.
As mentioned before, you can increase that with the resource_class feature. In my case, I had to set it to large.

build_and_test:
   docker:
     - image: circleci/openjdk:8-jdk
     - image: moveworkforward/atlas-run-standalone:jira-alpine

   resource_class: large

Summary

After following all those steps, we finally had our Cypress tests running in CircleCI.

This helps us be more confident after each code change since we can make sure our application is still working as expected.

Although in my case the application was a Jira plugin, I believe this approach can help you add integration tests to other applications that need some service running in the background.

Products we’re proud of

Articles you might like

Bring information from GitHub into Confluence
December 16, 2020
Bring information from GitHub into Confluence
Integrate GitHub with Confluence to increase team velocity and transparency. Enrich information about pull requests, read me and other files, issues and repositories. Know the state of those items without leaving Confluence.
Read more >
How to simplify project portfolio management using Jira
August 14, 2020
How to simplify project portfolio management using Jira
Jira is an incredibly powerful tool, however it may appear complex if not set up correctly. That’s why we’ve taken the time to help you set up what is called Project Central.
Read more >
How I passed 6 AWS exams in 2 months
April 19, 2021
How I passed 6 AWS exams in 2 months
At Move Work Forward we use heavily Amazon Web Services and many team members have passed multiple AWS Certifications. Here are the details of preparation for 6 AWS Certified exams in 2 months.
Read more >

New blog posts

Bitbucket Slack channel and hook overrides using patterns
August 4, 2021
Bitbucket Slack channel and hook overrides using patterns
In order to receive Slack notifications to different Bitbucket branches you need to create a pattern expression against source (from) or destination (to) branch.
Read more >
AWS vs Azure vs Google Cloud - Which Cloud Services is better for Enterprises?
July 17, 2021
AWS vs Azure vs Google Cloud - Which Cloud Services is better for Enterprises?
When selecting a cloud platform for your enterprise or organisation, it's almost as if you have an infinite amount of choices. Each service provider has its own set of benefits and features that make them stand out from the crowd, but there is no one best choice without considering all aspects such as budget constraints, available services, etc. Do some research on what type of services will suit your enterprise or organisation best, then decide based on this information.
Read more >
GitHub and GitLab Jira integration for Jira Data Center
July 8, 2021
GitHub and GitLab Jira integration for Jira Data Center
In this post, you can learn about Jira Data Center performance testing of GitHub and GitLab Jira integration App.
Read more >