Continuous Integration without unit tests

Continuous Integration without unit tests

Do you think continuous integration is not for you because you have no automated tests? Or no unit tests at all? Not true. Tests are important. But there are many more aspects to continuous integration than just testing.

1. Building the codebase

It is the most critical issue continuous integration should solve though. The main branch of your codebase should always build/compile.  It seems silly to even mention it.  

Take a team of 12. Say 1 faulty commit gets into the main branch. Everybody pulls. Here starts the process of finding what’s wrong and coordinating who should or will fix it. The confusion puts your whole team out of focus for around 30 minutes. Plus the frustration it brings.

Let’s say this happen once a week (everybody makes mistakes eventually). 30 minutes x 12 people is 8 lost hours per week.

If you are OK with that you might as well:

  • set up a CI process preventing faulty builds to get into the main branch
  • give away a day off to one developer every week

Same outcome, happier team :)

The effort to setup a CI process that ensures your codebase compiles is less than half a day work. It’s worth the effort.

2. Static code analysis

This comes for free in almost every language and is a one liner to run against a predefined set of rules:

Setting up the static code analysis (or linting) takes 1 hour or so. For what benefits?

You have well formatted and “by the book” code in your main branch. That’s a clear quality increase for your code base.

If that is the least of your problems because your team is always rushing to meet deadlines, think of it this way. Your code review process will be faster. Anything that is in the area of code structure, best practices etc. is already checked by your CI process. No need to review or discuss it. Your developers can focus on the business content of code reviews.

Great bonus: developers learn the code conventions automatically. The static analysis tool provides the violated rule and a why it is wrong to do so.

A hurdle with conventions is developers are dogmatic about tabs VS space kind of things. At the end of the day good conventions are ones followed by all. Pick a set of standard conventions and roll with it.

3. Culture change

Continuous Integration is not a technical problem. It’s a team process. You want to work in small increments and integrate code to the main branch often. See How to get started with CI for a larger discussion on what the culture goal actually is.

After the team masters the first critical elements, another shift should happen. People will realize that working in smaller increments is more efficient. Automated checks of basic mistakes will boost confidence to merge code faster. 

As a result branches life span will decrease. Code review will be faster. Every body will work with nearly latest code. It will prevent drifts and merge conflicts due to people working apart. See Why you should not use feature branches for a full list of benefits.

At the end of the day  CI works with our human pride and ego.  

Everybody would be happy for a tool to catch their mistake before it reaches the world. 

How do you get started?

Here is a very simple and actionable process to get started. It works regardless of your git provider: GitHub, Bitbucket, Gitlab, Azure DevOps, … and all the others.

1. Enable a Pull Request (PR) process

Lock your main branch from direct pushes. Everything should come through PRs. Here are links on how to do this for Github, Bitbucket, GitLab, Azure DevOps.

2. Pick a CI platform

Every git provider allows to define build pipelines for your PRs. The builds will run when the PR is created and for each new push to the branch the PR carries. A pre condition to complete your PR (= merge your branch) will be a succesfull build.

The big CI players are CircleCI, Codeship, Travis CI.

I of course recommend Fire CI since its the platform I’ve built. I don’t claim it is better than the rest for each and every use cases.

Pick one and get started.

3. Define a 2 liner build

The most basic build we want to achieve is build + static code analysis. Getting there is 2 or 3 commands in a shell.

All CI platforms go for “configuration as code”. You define your build in a *.yml file at the root of your repository and the platform picks it up.

With Fire CI for example you would need to add a .fire.yml file at the root of your repo that would look like this:

pipeline: 
  dockerfile: Dockerfile

Then you add a file named “Dockerfile” to build your app. Here are a few examples of simple Dockerfiles.

Any yarn/npm based tech like React/Angular/Vue/Node:

FROM python:3
WORKDIR /app 
COPY . .
RUN yarn
RUN yarn lint
RUN yarn build

Python:

FROM python:3
WORKDIR /app 
COPY . .
RUN pip install all_your_dependencies
RUN pylint all_your_python_files.py 

Go:

FROM golang:latest
WORKDIR /app
COPY . .
RUN go build -o main .

I could go on with many more. These examples are simplisitc and could be improved with a few more commands. But you get the point: it’s easy.

Optional: Enable code reviews

Now that every code contribution comes through a PR, code reviews are easy to do. Every git provider has an awesome UI to present the differences and allow you to comment on code.

If you are new to the process do not define a mandatory set of reviewers as it will slow your team down. Do start a best effort process to review each others code. And build on that.

What then?

As with everything, think big but start small. Having a CI process in place opens a world of opportunities.

Testing

Once you have the basic process in place, it becomes a breeze to add your first automated test. And then some others. Low yet continuous effort can bring you an awesome test coverage before you know it.

I recommend you remain lean and not invest effort to “let’s write some tests”. Check what breaks often or requires a high effort to test manually. Automate that. 

Always keep productivity in mind. Having a ton of tests just because is worth nothing.

Other perks

There are many tools out there that you can integrate to your CI process. They are not key but the effort VS benefits could be worthwile.

A few examples below. Links are for the GitHub marketplace but other git providers integrate as easily.

  • Automatic update of dependencies: Depfu suggests you dependencies updates automatically. This way you remain up to date doing small increments. Always better than a once a year “let’s bump everything” strategy

  • Open source security: Snyk warns you about security threats in open source libraries

  • Images optimisation: ImgBot detects large images in your repository. And submits a PR with size optimized version. Relevant for frontend projects, but still nice.

There are many more out there. Browse the marketplace for things that could solve a problem for you.

Careful though! Resist the urge to use everything that comes to mind. Pick the ones that really provide a productivity boost. Free metrics or tools that are not looked at are harmful as people are not sure what to do with them.

Conclusion

You do not need fancy tests suites to get started with Continuous Integration. 

Literally 2 hours of effort can get you rolling. And enable a virtuous circle for your team productivity.

The bigger your team and your projects, the greater the benefits. In 2020 there is no good reason to not have a CI process.

Feel free to contact me if you need help setting up a CI process for your team. I’ll be happy to help if I can.

Thanks for reading and good luck!

(the awesome cover photo is from Will Porada on Unsplash)

Jean-Paul Delimat
Jean-Paul Delimat Fire CI's founder