Paulund
2018-08-26 #git

Automatically Run PHPUnit Tests Before Git Push

When you're working on a project with a strong test suite you'll want to make sure that everything you push to the repository doesn't break any of the tests that you have in your project.

This means that before you preform a git push you'll need to make sure you run phpunit and that all your tests have passed.

In this tutorial we're going to add a rule into your git repository to make sure that we can't push any new code into the repository without the tests passing, to do this we're going to use git hooks.

Git Hooks

Git hooks allow us to run events at different stages of the git process, from these events we can run what ever commands we want exit the process if that command fails.

These are the git hooks that we have available to use

  • applypatch-msg
  • commit-msg
  • post-update
  • pre-applypatch
  • pre-commit
  • pre-commit
  • prepare-commit-msg
  • pre-push
  • pre-rebase
  • pre-receive
  • update

Each of these are triggered at different times in your git process. To view all the git hooks go to the root of your project and type ls .git/hooks/ this will show you a list of the git hooks available.

To run our phpunit tests we're going to use the pre-push hook that runs before we push to the repository.

Pre-push

Add a new file to .git/hooks/pre-push, open the file and add the following.

#!/bin/bash

git diff --cached --name-only | while read FILE; do
if [[ "$FILE" =~ ^.+(php|inc|module|install|test)$ ]]; then
    echo "Running tests..."
    cd "${0%/*}/.."
    phpunit 1> /dev/null
    if [ $? -ne 0 ]; then
      echo -e "\e[1;31m\tUnit tests failed ! Aborting commit.\e[0m" >&2
      exit 1;
    fi
fi
done || exit $?

Let's break down what this does

git diff --cached --name-only | while read FILE; do

Will return all the changed files in the commit.

if [[ "$FILE" =~ ^.+(php|inc|module|install|test)$ ]]; then

Then make sure that we only match on the above pattern so we know a php or test file has changed and therefore we need to run tests.

cd "${0%/*}/.."

This will cd to the root of the project.

    phpunit 1> /dev/null
    if [ $? -ne 0 ]; then
      echo -e "\e[1;31m\tUnit tests failed ! Aborting commit.\e[0m" >&2
      exit 1;
    fi

We then run phpunit command and if the command is not 0 then the unit tests have failed and we abort the commit.