Blog Post

Getting Started with Code Coverage for PHP

March 26, 2023 Tom Hu

PHP, developed in 1995, is one of the most popular programming languages in the world. This article will walk you through an example php project to get up and running with testing and code coverage. You can view the entire source code of this post at our example repository.

For our project, we will be using php 8.2.1. You will need to create a new public repository in GitHub. You should also go ahead and create a Codecov account.

Getting started with php

First, make sure that you have composer installed on your system. This will help to manage dependencies and make your php experience richer.

After installing, add a composer.json file to your project.

{
    "name": "codecov/example-php",
    "type": "library",
    "license": "MIT",
    "description": "Codecov Example PHP",
    "require": {
        "php": ">=8.2"
    },
    "require-dev": {
        "phpunit/phpunit": "~9.5"
    },
    "autoload": {
        "files": [
            "calculator/BasicCalculator.php"
        ]
    }
}

This will help create a bare php project.

Create a directory, calculator and test.

mkdir calculator && mkdir test

We will start with a simple calculator app that exposes two functions: add and subtract. Both functions accept two arguments and return a number. We can paste the code below into the file calculator/BasicCalculator.php

<?php
namespace Calculator;

class BasicCalculator
{
    public static function add(float $x, float $y) {
        return $x + $y;
    }

    public static function subtract(float $x, float $y) {
        return $x - $y;
    }
}

Now, let’s add a test for our add function.

test/calculatorTest.php

<?php
require 'vendor/autoload.php';

use Calculator\BasicCalculator;

class calculatorTest extends PHPUnit\Framework\TestCase
{
    /**
     * @covers Calculator\BasicCalculator
    */
    public function testAdd()
    {
        $this->assertEquals(BasicCalculator::add(1, 2), 3.0);
    }
}

Run your tests and get coverage

To run our coverage, we will need to first install the dependencies. In a terminal, run

composer self-update && composer install && composer dump-autoload

To run our coverage, run

vendor/bin/phpunit --coverage-text .

This should give us the following output

.                                                                   1 / 1 (100%)

Time: 00:00.029, Memory: 8.00 MB

OK (1 test, 1 assertion)


Code Coverage Report:
  2023-03-14 03:12:47

 Summary:
  Classes:  0.00% (0/1)
  Methods: 50.00% (1/2)
  Lines:   50.00% (1/2)

Calculator\BasicCalculator
  Methods:  50.00% ( 1/ 2)   Lines:  50.00% (  1/  2)

How to upload to Codecov

Now that we are able to collect coverage locally, let’s learn how to upload these reports to Codecov. Codecov is a code coverage tool that provides reports on how much of a project’s codebase is tested. It is often used in conjunction with continuous integration (CI) systems to ensure that new code changes are adequately covered by tests.

We will be using GitHub Actions as the CI and the Codecov Action to upload coverage reports.

Create a file called .github/workflows/ci.yml.

name: Workflow for Codecov example-php
on: [push, pull_request]
jobs:
  run:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Set up php 8.2
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'
      - name: Install dependencies
        run: composer self-update && composer install && composer dump-autoload
      - name: Run tests and collect coverage
        run: vendor/bin/phpunit --coverage-clover coverage.xml .
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v3

It is recommended that you install the Codecov app for this repository to prevent rate-limiting issues. Save your code and push up to GitHub.

git checkout -b 'initial-commit'
git add .
git commit -m 'Initial commit and upload coverage to Codecov'
git push origin initial-commit

In GitHub, open the pull request and wait for CI and Codecov to finish running and analyzing. You should see the following pull request commit.

You should also see four status checks, two of which come from Codecov.

Our documentation contains more information on the meaning of each status check. When you are ready, merge the pull request.

Covering uncovered code

Now that we can get coverage data in our pull request. Let’s take a look at how to increase coverage.

Let’s take a look at the coverage report from Codecov. Navigate to your repository from the Codecov UI. You should see a dashboard like this.

Notice that there are only 2 covered lines in the Code tree. If we click on calculator, and BasicCalculator.php, we’ll come to the file view.

From this view, we can tell that we haven’t written a test for our subtract function!

Create a new branch in your terminal

git checkout main
git pull
git checkout -b 'subtract-test'

and update the test file test/calculatorTest.php with the following code below the add test.

    /**
     * @covers Calculator\BasicCalculator
    */
    public function testSubtract()
    {
        $this->assertEquals(BasicCalculator::subtract(1, 2), -1.0);
    }

Save the code and open a new pull request.

git add .
git commit -m 'fix: add tests for subtract fn'
git push origin subtract-test

Notice the Codecov comment shows the coverage increasing from 50.00% to 100.00%.

Advanced Codecov configurations

Now that you have uploaded your first Ruby coverage reports successfully to Codecov, you can check out some of our other features including

Before we redirect you to GitHub...
In order to use Codecov an admin must approve your org.