Git Product home page Git Product logo

phpunit-clever-and-smart's Introduction

Clever Test Runner for PHPUnit

Build Status Dependency Status Average time to resolve an issue Percentage of issues still open

Mission

Enable fast feedback cycles by storing test case results in a database and reorder tests on consecutive runs in the following order:

  1. Failures and errors
  2. So far unrecorded tests
  3. Remaining tests by execution time in ascendant order (fastest first)

It’s probably not yet very stable but try it out.

What it does

Run a test suite once with errors

PHPUnit 3.7.28 by Sebastian Bergmann.

.............................................FSFS..............  63 / 280 ( 22%)
............................................................... 126 / 280 ( 45%)
............................................................... 189 / 280 ( 67%)
............................................................... 252 / 280 ( 90%)
.........................

Rerun that test suite and see how the previous failing tests have been sorted to the beginning of the test run:

PHPUnit 3.7.28 by Sebastian Bergmann.

FSFS...........................................................  63 / 280 ( 22%)
............................................................... 126 / 280 ( 45%)
............................................................... 189 / 280 ( 67%)
............................................................... 252 / 280 ( 90%)
.........................

Installation

add the following line to your projects' composer.json require-dev section.

"lstrojny/phpunit-clever-and-smart": "0.*"

Configuration

To play around with it, add this to your phpunit.xml(.dist)

    <listeners>
        <listener class="PHPUnit\Runner\CleverAndSmart\TestListener">
            <arguments>
                <object class="PHPUnit\Runner\CleverAndSmart\Storage\Sqlite3Storage"/>
            </arguments>
        </listener>
    </listeners>

you might alter the location of the sqlite storage file, by passing a path to the Sqlite3Storage class:

    <listeners>
        <listener class="PHPUnit\Runner\CleverAndSmart\TestListener">
            <arguments>
                <object class="PHPUnit\Runner\CleverAndSmart\Storage\Sqlite3Storage">
                    <arguments>
                        <string>/my/path/to/.phpunit-cas.db</string>
                    </arguments>
                </object>
            </arguments>
        </listener>
    </listeners>

Roadmap

  • Test it with as many test suites as possible
  • Stabilize
  • Merge into PHPUnit core

phpunit-clever-and-smart's People

Contributors

lstrojny avatar staabm avatar uuf6429 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

phpunit-clever-and-smart's Issues

phpunit fails if sqlite database is locked

When running multiple tests in parallel the database of phpunit-clever-and-smart might locked for a short moment. Sometimes this leads to phpunit aborting execution.

Here's the error message with stack trace:

Warning:  SQLite3::query(): Unable to prepare statement: 5, database is locked in /myapp/vendor/lstrojny/phpunit-clever-and-smart/src/PHPUnit/Runner/CleverAndSmart/Storage/Sqlite3Storage.php on line 185
Stack trace:
   1. {main}() /myapp/vendor/phpunit/phpunit/phpunit:0
   2. PHPUnit_TextUI_Command::main() /myapp/vendor/phpunit/phpunit/phpunit:36
   3. PHPUnit_TextUI_Command->run() /myapp/vendor/phpunit/phpunit/src/TextUI/Command.php:105
   4. PHPUnit_TextUI_TestRunner->doRun() /myapp/vendor/phpunit/phpunit/src/TextUI/Command.php:153
   5. PHPUnit_TextUI_TestRunner->handleConfiguration() /myapp/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:153
   6. PHPUnit_Util_Configuration->getListenerConfiguration() /myapp/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:714
   7. PHPUnit_Util_XML::xmlToVariable() /myapp/vendor/phpunit/phpunit/src/Util/Configuration.php:342
   8. PHPUnit\Runner\CleverAndSmart\Storage\Sqlite3Storage->__construct() /myapp/vendor/phpunit/phpunit/src/Util/XML.php:245
   9. PHPUnit\Runner\CleverAndSmart\Storage\Sqlite3Storage->query() /myapp/vendor/lstrojny/phpunit-clever-and-smart/src/PHPUnit/Runner/CleverAndSmart/Storage/Sqlite3Storage.php:34
  10. PHPUnit\Runner\CleverAndSmart\Storage\Sqlite3Storage->doQuery() /myapp/vendor/lstrojny/phpunit-clever-and-smart/src/PHPUnit/Runner/CleverAndSmart/Storage/Sqlite3Storage.php:159
  11. SQLite3->query() /myapp/vendor/lstrojny/phpunit-clever-and-smart/src/PHPUnit/Runner/CleverAndSmart/Storage/Sqlite3Storage.php:185
 Fatal error:  Uncaught exception 'PHPUnit\Runner\CleverAndSmart\Exception\StorageException' with message 'database is locked (error code 5)' in /myapp/vendor/lstrojny/phpunit-clever-and-smart/src/PHPUnit/Runner/CleverAndSmart/Exception/StorageException.php:8

Maybe we can change this behaviour to "wait a second and try again" or at least to ignore this exception (maybe print a warning to stderr).

Travis support

I am not sure if it is at all possible, but I think we can discuss things here:

Atm I don't see a chance to use the testlistener in travis builds because all storage results are local in the build and cannot persist between ci builds.

One solution could use a remote db/webservice as a remote storage for travis builds. But maybe there is even a easier way to achieve the same thing?

"randomize order"

More like a feature request.
I once worked on a huge project where we couldn't run tests in isolation mode because of the amount of time that added on top of the already lengthy cycle. Without knowing we introduced a couple dependencies between tests that resulted in a lot of sh*t later. Having the option to randomise execution would've prevented this sort of behaviour.

Garbage collection algorithm for database

Think of a clever way to keep the database clean

Ideas for strategies

  • Multiples of average of tests count
  • Result age
  • SQLite file size
    -- Find out size when it becomes significantly slower

Batch insert / update

Investigate if pushing each insert/update to a queue and and execute it in batches in a shutdown function would reduce IO and speedup things.

Benchmark

Add a testsuite of a stable external project (maybe just a released version) and compare suite runtime with and without clever&smart test listener to measure the actual overhead

Test ordering and depends

Some tests are being marked as skipped because they depend on another test. The test in question passed but the others were skipped.

This is happenning in a private repo of which I can't provide the code, but i'll try to reproduce the issue in a public repo ASAP.

Sqlite db file not found when running on Travis CI

Hey there and thanks for CaS, it's a little tool I love (and believe it should be part of PHPUnit's core).

I just had some problems getting the listener to work with Travis CI. Usually paths like src/ or build/... resolve in PHPUnit's XML config.

When I configure CaS with a relative path I get the following problem:

Stack trace:
#0 /home/travis/build/mihaeu/movie-manager/vendor/lstrojny/phpunit-clever-and-smart/src/PHPUnit/Runner/CleverAndSmart/Storage/Sqlite3Storage.php(24): SQLite3->__construct('build/.phpunit-...')
#1 [internal function]: PHPUnit\Runner\CleverAndSmart\Storage\Sqlite3Storage->__construct('build/.phpunit-...')
#2 phar:///home/travis/.phpenv/versions/5.4.32/bin/phpunit/phpunit/Util/XML.php(276): ReflectionClass->newInstanceArgs(Array)
#3 phar:///home/travis/.phpenv/versions/5.4.32/bin/phpunit/phpunit/Util/Configuration.php(374): PHPUnit_Util_XML::xmlToVariable(Object(DOMElement))
#4 /home/travis/build/mihaeu/movie-manager/vendor/phpunit/phpunit/src/TextUI/TestRunner.php(722): PHPUnit_Util_Configuration->getListenerConfiguration()
#5 /home/travis/build/mihaeu/mo in /home/travis/build/mihaeu/movie-manager/vendor/lstrojny/phpunit-clever-and-smart/src/PHPUnit/Runner/CleverAndSmart/Storage/Sqlite3Storage.php on line 24

https://travis-ci.org/mihaeu/movie-manager/jobs/37203163#L249

I played around a bit and solved it by extending Sqlite3Storage

<?php

namespace Mihaeu\MovieManager\Tests;

use PHPUnit\Runner\CleverAndSmart\Storage\Sqlite3Storage;

class Sqlite3TestStorage extends Sqlite3Storage
{
    public function __construct($fileName = '.phpunit-cas.db')
    {
        $fileName = realpath(__DIR__.'/../../..').'/'.$fileName;
        if (!file_exists(dirname($fileName))) {
            mkdir(dirname($fileName), 0777, true);
        }
        parent::__construct($fileName);
    }
}

Of course it's not a nice solution, but it works in my case (the path has to be adjusted of course if loaded from a vendor dir). In the case of Travis getcwd() could be used to find the base path as well. Of course using CaD on Travis doesn't make much sense, because there are no repeated test runs, but it would be nice to be able to use the same phpunit.xml

What do you think?

Skipped test classes crash phpunit

The following test will crash PHPUnit if phpunit-clever-and-smart is registered as a test listener:

/**
 * Class ExampleCrashTest
 *
 * @requires function i_dont_exist
 */
class ExampleCrashTest extends PHPUnit_Framework_TestCase
{

}

Apparently, if an entire class is skipped instead of a single test method, a PHPUnit_Framework_TestSuite object is passed to \PHPUnit\Runner\CleverAndSmart\TestListener::addSkippedTest. This object implements the \PHPUnit_Framework_Test interface. However in \PHPUnit\Runner\CleverAndSmart\Storage\Sqlite3Storage::record, suddenly a \PHPUnit_Framework_TestCase object is required. The typehint fails, crashing the phpunit process.

Fatal error: Uncaught exception 'ErrorException' with message 'Argument 2 passed to PHPUnit\Runner\CleverAndSmart\Storage\Sqlite3Storage::record() must be an instance of PHPUnit_Framework_TestCase, instance of PHPUnit_Framework_TestSuite given, called in /Users/willem/Sites/mollie/vendor/lstrojny/phpunit-clever-and-smart/src/PHPUnit/Runner/CleverAndSmart/TestListener.php on line 107 and defined' in /Users/willem/Sites/mollie/vendor/lstrojny/phpunit-clever-and-smart/src/PHPUnit/Runner/CleverAndSmart/Storage/Sqlite3Storage.php on line 73

Call stack:

Call Stack:
    0.0003     225232   1. {main}() /Users/willem/Sites/mollie/vendor/phpunit/phpunit/phpunit:0
    0.0099     712344   2. PHPUnit_TextUI_Command::main() /Users/willem/Sites/mollie/vendor/phpunit/phpunit/phpunit:47
    0.0099     712984   3. PHPUnit_TextUI_Command->run() /Users/willem/Sites/mollie/vendor/phpunit/phpunit/src/TextUI/Command.php:109
    0.0099     715912   4. PHPUnit_TextUI_Command->handleArguments() /Users/willem/Sites/mollie/vendor/phpunit/phpunit/src/TextUI/Command.php:120
    0.0160    1146544   5. PHPUnit_TextUI_Command->handleBootstrap() /Users/willem/Sites/mollie/vendor/phpunit/phpunit/src/TextUI/Command.php:633
    0.0166    1154992   6. PHPUnit_Util_Fileloader::checkAndLoad() /Users/willem/Sites/mollie/vendor/phpunit/phpunit/src/TextUI/Command.php:804
    0.0168    1155152   7. PHPUnit_Util_Fileloader::load() /Users/willem/Sites/mollie/vendor/phpunit/phpunit/src/Util/Fileloader.php:38
    0.0170    1167880   8. include_once('/Users/willem/Sites/mollie/tests/bootstrap.php') /Users/willem/Sites/mollie/vendor/phpunit/phpunit/src/Util/Fileloader.php:56
    0.6078    5443552   9. require_once('/Users/willem/Sites/mollie/scripts/phpstorm/ide-phpunit-9.php') /Users/willem/Sites/mollie/tests/bootstrap.php:47
    0.6102    5496072  10. IDE_Base_PHPUnit_TextUI_Command::main() /Users/willem/Sites/mollie/scripts/phpstorm/ide-phpunit-9.php:553
    0.6102    5496696  11. PHPUnit_TextUI_Command->run() /Users/willem/Sites/mollie/scripts/phpstorm/ide-phpunit-9.php:296
    0.6202    6172160  12. PHPUnit_TextUI_TestRunner->doRun() /Users/willem/Sites/mollie/vendor/phpunit/phpunit/src/TextUI/Command.php:158
    0.6437    6470952  13. PHPUnit_Framework_TestSuite->run() /Users/willem/Sites/mollie/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:436
    0.6551    6810536  14. PHPUnit_Framework_TestResult->addFailure() /Users/willem/Sites/mollie/vendor/phpunit/phpunit/src/Framework/TestSuite.php:705
    0.6740    8401768  15. PHPUnit\Runner\CleverAndSmart\TestListener->addSkippedTest() /Users/willem/Sites/mollie/vendor/phpunit/phpunit/src/Framework/TestResult.php:329
    0.6741    8401848  16. PHPUnit\Runner\CleverAndSmart\Storage\Sqlite3Storage->record() /Users/willem/Sites/mollie/vendor/lstrojny/phpunit-clever-and-smart/src/PHPUnit/Runner/CleverAndSmart/TestListener.php:107
    0.6741    8403248  17. PHPUnit_Util_Fileloader::{closure:/Users/willem/Sites/mollie/core/tests/bootstrap.php:15-23}() /Users/willem/Sites/mollie/vendor/lstrojny/phpunit-clever-and-smart/src/PHPUnit/Runner/CleverAndSmart/TestListener.php:73

Executing phpuint prompt Interface'PHPUnit_Framework_TestListener' not found

  • php version

PHP 7.2.34-1+ubuntu18.04.1+deb.sury.org+1 (cli) (built: Oct 6 2020 12:01:28) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
with Zend OPcache v7.2.34-1+ubuntu18.04.1+deb.sury.org+1, Copyright (c) 1999-2018, by Zend Technologies

  • phpunit version

PHPUnit 7.5.20 by Sebastian Bergmann and contributors.

  • phpumit.xml
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="vendor/autoload.php"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stderr="true"
         stopOnFailure="false"
         verbose="true"
         colors="true">
   ...
    <listeners>
        <listener class="PHPUnit\Runner\CleverAndSmart\TestListener">
            <arguments>
                <object class="PHPUnit\Runner\CleverAndSmart\Storage\Sqlite3Storage"/>
            </arguments>
        </listener>
    </listeners>
    ...
</phpunit>
  • error message
 PHP Fatal error:  Interface 'PHPUnit_Framework_TestListener' not found in /path/vendor/lstrojny/phpunit-clever-and-smart/src/PHPUnit/Runner/CleverAndSmart/TestListener.php on line 15

How can I solve the problem that PHPUnit_Framework_TestListener does not exist?

output info about the registered testlistener

I think it would help debugging and configure the runner if it would output a message like Running testsuite using clever-and-smart before the actual test suite run so people see immediately that they use a different setup...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.