Inline with what Arman P. said. When running your tests, make sure you have a docker image which contains all the tools that you will need for your build/test.
You have two options:
You can build your own image, with all the tools you need, and
maintain this as your project evolves; or,
you can simply install a basic image from the docker hub and install
all the tools before you run your jobs.
Both options have their pros and cons:
Option (1) gives you complete control, but you would need to add this to a private registry which the CI can pull from (Gitlab gives you a private registry support). The only slight con here is that you would have to setup the private registry (e.g Gitlab's) first. Not too difficult, and only need to do it once.
But then it is up to you to maintain the images, etc.
Option (2) allows you to run all the tools without having to maintain a private registry or the docker containers. You simply run the install scrips before your jobs as Arman P. mentioned. The disadvantage on that is that your jobs and builds/tests take longer to run as you now have to wait for the install to happen before every run.
A simple example: Using option (2)
We need PHPUnit and composer.
So, use a container from the public docker hub which has php: select one that has the version of PHP you want to test (e.g. 5.6 or 7). Let's assume 5.6.
In that container we need to install composer and PHPUnit before we can run our tests. This is what your CI file might look like:
.gitlab-ci.yml
image: php:5.6.25-cli
stages:
- build
- test
.install_composer_template:&install_composer
- apt-get install -y git
- curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
before_script:
<<:*install_composer
build app:
stage: build
script:
- composer install
- composer dump-autoload -o
test app:
stage: test
before_script:
<<:*install_composer
- composer global require -q phpunit/phpunit
script:
- phpunit --colors=always
Quick summary of what this actually does
Every job -- here we only have "build app" and "test app" -- will run through the official PHP 5.6 image.
We have two stages defined, build and test -- note: these are defined by default, but here we are being explicit for clarity.
The first job that runs will be the "build app" as it occurs in the first stage, build. Before the script runs in this job, the global before_script runs, which installs git and composer (Composer requires Git). Then the script runs and installs all our composer dependencies. Done.
The next stage then executes, which is test. So our jobs attached to that run (in parallel if we had more than one), which for us is just "test app". Here, we use YML features to reuse the install composer instructions: the local before_script overrides the global before_script, installing Composer (via the YML template) and PHPUnit. Then the actual script runs: which runs our unit tests. The unit tests assume you have a phpunit config in the root -- you can customise this command as you would on you own terminal.
Note here, that due to the stage setup, the output of the build stages are automatically made available in the test stage. So we don't have to do anything, Gitlab will pass all the files for us!
The main reason for using the install_composer template is to improve job execution time. Most things are going to require Composer. So we have a global template and a script that runs for every job. If you need something a bit more specific, with tools that are only required for that job, e.g. PHPUnit, then override the before_script locally in the job and install the required tools. This way we don't have to install a whole load of tools which we might not need in every job!