Testing software can be an expensive part of the release cycle. Not only do you have to verify that new changes are working as expected, but you also need to make sure that existing features have not broken. This can quickly become a significant burden as the scope of testing increases with each new release. It's also a tedious task for your team as they'll have to manually check basic aspects of your application time and time again.

Test automation exists to solve this issue by eliminating the redundant and annoying aspect of testing. You write a test once, and it can be automatically executed by a testing framework, without the need for human intervention. Then you can go one step further and hook your repository on a continuous integration (CI) service like Bitbucket Pipelines to run your tests automatically on every change that gets pushed to the main repository.

In this tutorial, we'll see how to set up a CI workflow in Bitbucket Pipelines with a simple Node.js example. We'll start by building our app; then we'll look at how we can implement a simple test, and finally, we'll learn how to hook it up to Bitbucket Pipelines.

Step 1: Build a simple Hello World application

To begin our tutorial, we'll start by creating a basic Node.js application that displays "Hello World!" in the browser. It's the same code as the example application in the Express framework, and even if you're not using Node, it should be easy to understand and adapt to your need. If you want to skip this part, you can find the final code of the application in Bitbucket.

Start by creating a directory and run npm init to initialize your new Node project. You can use all the default settings except for the entry point that you need to change to server.js instead of index.js.

mkdir helloworld cd helloworld npm init

Your npm init settings

If you forgot to change the entry point to server.js don't worry as you can edit it after in your package.json file. When you're done your helloworld directory should have a single file called package.json, and it should look like this:

Now we will install Express which is a web framework for Node. We'll save it as a dependency with the --save parameter. It's important to save it explicitly as a dependency because it will allow later Bitbucket Pipelines to know what dependencies needs to be installed to test your application.

npm install express --save

Create a file called server.js and copy and paste the code below to create your Hello World application.

Step 2: Write a test for our application

Now that we have our application up and running we can start writing a test for it. In this case, we will make sure that it always displays "Hello World!" properly when the user calls the base URL. This is a very basic example, but following the same structure you will be able to add unit tests for your own application, but also do more complex things such has checking authenticating, creating and deleting content, testing permissions.

To do that we'll use a test framework called Mocha and a library called supertestwhich will help manage HTTP requests in our tests. When comes the time for you to add test automation to your application, take some time to research the right testing framework for you. Depending on the language, the options may vary. Some frameworks are quite established like PHPUnit for PHP but in other cases you might have to explore a bit to understand which test framework will be the best fit for your project. You can find an exhaustive list of unit testing frameworks on Wikipedia but we recommend to approach the developer community of your language to get some recommendations.

Run the command below in your terminal to install both Mocha and supertest as development dependencies for your application.

If you run npm test again in your terminal you should now see that one test is passing.

Congratulations! You now have implemented an automated test for your app. This is just a stepping stone for you to embrace CI and as you build your own application you should look into the different kind of teststhat you can implement to check the integrity of your system. Just remember that the more complicated the tests are, the more expensive they will be to run.

In this tutorial, we've implemented a feature and then wrote a test for it. It can be interesting to do the opposite and start by writing the tests that should verify your feature. Then you can implement the feature knowing that you already have safeguards to make sure that it's working as expected.

Your test is now scripted and you can run it via the command line. But to start practicing CI you have to make sure that your test suite is run for every new commit. That way developers are alerted as soon as their changes break the application and they can fix the underlying issue right away before moving to their next task. The other advantage of running your tests on every commit is that it can help your team assess the quality of the development – you will be able to visually see how many times new changes break your application, and how quickly things get back to a healthy state.

This may seem daunting but thankfully, automating your tests can easily be done with with Bitbucket Pipelines.

Start by adding your repository to Bitbucket.

Go to Pipelines by clicking on the corresponding menu item in the sidebar.

After enabling Pipelines, pick the Node.js template in the configuration example. This example should have the command npm install and npm test in the script section and Bitbucket Pipelines will run they just like you would have in your own terminal to install dependencies and run the tests.

You shouldn't need to modify the bitbucket-pipelines.yml file and you can commit it straight to your repository.

After committing your file you will be taken to the Pipelines section where you can see your first pipeline running.

You can click on the pipeline to see the detail of the run and keep track of it until it finishes successfully.

That's it! Your Bitbucket repository has a CI workflow set up and your tests will be run on every commit. You can try this by introducing changes in the code and monitor the Pipelines section. If your changes are good things will be green, but if you break the application or change the phrase that is displayed on the homepage you should see a failing pipeline and you'll receive an alert in your emails.

An email alert after introducing a breaking change

What's next

Obviously, this example is far from the application that you're currently building. However, it should give you a basic understanding of test automation and how to get a continuous integration workflow set up:

Find the right testing framework

Implement your tests

Enable Bitbucket Pipelines

To truly get value out of CI you'll need to keep on adding new tests for each new feature, improvement or bug fix that you ship. If the scope of your test suite is too small you will end up having a false sense of confidence that your application is working. Adopting continuous integration is a cultural change and it requires your entire team to embrace to fully work. You can learn more by reading our CI guide.

Share this article

Sten Pittet

I've been in the software business for 10 years now in various roles from development to product management. After spending the last 5 years in Atlassian working on Developer Tools I now write about building software. Outside of work I'm sharpening my fathering skills with a wonderful toddler.