Search code examples
laravelphpunitcode-coveragelaravel-5.4laravel-dusk

Code coverage for laravel dusk


Is there any way to get code coverage when running Laravel Dusk?

I know it runs browser tests so it's not scrutinizing code, but is there a way to add a listener to check what code is covered? I did not see anything on this subject now.


Solution

  • Conceptually, you need to bootstrap all your requests w/ PHP Unit's code coverage tools.

    You can do this with phpunit libraries directly, or via xdebug's coverage tools (which use phpunit).

    From this sample gist that I found, you can start coverage tools based on a couple of _GET parameters passed via the Dusk test.

    public function testBasicExample()
    {
          $this->browse(function (Browser $browser) {
              $browser->visit(route('test', [
                  'test_name' => 'testBasicExample',
                  'coverage_dir' => '/app/Http'
              ]))->assertSee('test');
          });
      }
    

    The code that does the work is two parts 1. Start collecting based on parameters:

    $test_name = $_GET['test_name'];
    require __DIR__ . '/../vendor/autoload.php';
    $current_dir = __DIR__;
    $coverage = new SebastianBergmann\CodeCoverage\CodeCoverage;
    $filter = $coverage->filter();
    $filter->addDirectoryToWhitelist(
        $current_dir . '/..' . ((isset($_GET['coverage_dir']) && $_GET['coverage_dir'])
            ? $_GET['coverage_dir']
            : '/app')
    );
    $coverage->start($test_name);
    

    And 2 end collecting and output:

    function end_coverage()
    {
        global $test_name;
        global $coverage;
        global $filter;
        global $current_dir;
        $coverageName = $current_dir . '/coverages/coverage-' . $test_name . '-' . microtime(true);
        try {
            $coverage->stop();
            $writer = new \SebastianBergmann\CodeCoverage\Report\Html\Facade;
            $writer->process($coverage, $current_dir . '/../public/report/' . $test_name);
            $writer = new SebastianBergmann\CodeCoverage\Report\PHP();
        } catch (Exception $ex) {
            file_put_contents($coverageName . '.ex', $ex);
        }
    }
    

    The end collection is called using a clever little trick where the class coverage_dumper has just a destructor, which gets called automatically when php ends the process.

    The code itself can use a bit of tidy up as far as output paths, and variables go, but from a concept, it should work.