Travis CI: No Rakefile found (looking for: rakefile, Rakefile, rakefile.rb, Rakefile.rb)

Bei der sehr kryptischen Fehlermeldung in Travis CI:

No Rakefile found (looking for: rakefile, Rakefile, rakefile.rb, Rakefile.rb)

handlet es sich um ein Problem mit falschen Einrückungen im travis.yml File:

matrix:
  include:
    - php: 5.6
      env:
        - SYMFONY_VERSION='3.4.*'

Ein Leerzeichen zu wenig in der Zeile – SYMFONY_VERSION=’3.4.*’ und es kommt zu diesem wenig aufschlussreichen Fehler.

GitHub Continuous Integration und CodeCoverage mit Travis CI

Für mein öffentliches GitHub Projekt Entity to Rest Bundle für Symfony, habe ich Travis CI, ein Service einer Frima aus Berlin/Friedrichshain, für Continuous Integration benutzt und bin vollbegeistert. Ich musste nur eine .travis.yml erstellen und mich mit meinem Github Account kostenlos anmelden und mit wenigen Handgriffen kann ich jetzt mittels Travis CI:

  • Testen von unterschiedlichen PHP-Versionen
  • Testen von unterschiedlichen Symfony Versionen
  • Markup auf GitHub über den Stand der Tests: Build:success/failed
  • automatische E-Mail Benachrichtigung über das Ergebnis nach jedem Pull-Request

Jetzt erscheint eine schicke Grafik und informiert über den aktuellen Build Status:

travis_github_ci

Das Ergebnis des Builds kann man sich anschauen auf der travis ci Webseite.

Hinweis: Für öffentliche GitHub Repositories ist der Service kostenlos, für private Repositories muss man bezahlen.

Um die CodeCoverage auch anzeigen und berechnen zu können, kann man sich kostenlos bei einem der beiden Anbieter anmelden und muss nur die CodeCoverage Generierung in seiner .travis.yml triggern.

https://codecov.io  Beispiel Projekt

https://coveralls.io Beispiel Projekt

Symfony Entity to REST API Bundle released

Bei meinem jetztigen Projekt programmiere ich gerade mit Symfony 3 eine REST API und habe aus verschiedenen Bundlen eine REST Suite erstellt für Symfony 3 erstellt, welche folgende  Komponenten enthält:

  • Api Dokumentation inkl Sandbox Tests – auch ohne Programmierkenntnisse kann der Code abgenommen werden und ausprobiert werden
  • die Dokumentation wird automatisch generiert aus den Eigenschaften der Entitäten, es ist kein zusätzlicher Aufwand notwendig
  • die Validierung der Parameter wird automatisch anhand der Entitäten durchgeführt, es ist kein zusätzlicher Aufwand notwendig
  • eine Suche ist automatisch enthalten, die Relationen von Entitäten sind auch durchsuchbar
  • CRUD Funktionalität: GET, CREATE, UPDATE, DELETE einer Entität ist schon implementiert und kann erweitert werden
  • einfaches Testing: Integration Tests sind schnell erstellbar / Vorlagen liegen bereit
  • ein Demo REST Service Projekt mit Demo Code ist bereit
  • ausführliche Dokumentation
  • einfache Installation über composer: composer require sebvie/rest-suite-bundle

Bei Interesse kann ich gern das Bundle in ihrem Projekt integrieren oder einarbeiten: Kontakt.

 

 

Symfony static laden von Fixtures beim Laden eines Integration Tests in PHPUnit

Mit der statischen Funktion setUpBeforeClass() von PHPunit kann man einmalig vor dem durchführen der Tests  in einer Klasse Fixtures laden und die Datenbank zurücksetzen:

class MyTestCase extends WebTestCase
{
    use FixtureLoadTrait;
 /**
 * @return void
 */
 public static function setUpBeforeClass()
 {

     $fixtures = [
         new TriggerConditionFixture()
     ];
     self::rebuildDataBase($fixtures);
 }

Die Fixtures lassen sich bequem mit dem Trait laden und die Datenbank wird geleert:

<?php

namespace Tests\Integration;

use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
use Symfony\Bridge\Doctrine\DataFixtures\ContainerAwareLoader;
use Tests\Fixture\BackendBundle\DataFixtures\ORM\LoginFixture;

trait FixtureLoadTrait
{

    /**
     * @param array $fixtures
     *
     * @return void
     */
    protected static function rebuildDataBase(array $fixtures)
    {
        self::bootKernel();
        $fixtureLoader = new ContainerAwareLoader(
            self::$kernel->getContainer()
        );
        foreach($fixtures as $fixture){
            $fixtureLoader->addFixture($fixture);
        }
        $fixtureLoader->addFixture(new LoginFixture());
        self::getFixtureExecutor()->execute($fixtureLoader->getFixtures());
    }

    /**
     * @return ORMExecutor
     */
    protected static function getFixtureExecutor()
    {
        /** @var \Doctrine\ORM\EntityManager $entityManager */
        $entityManager = self::$kernel->getContainer()
            ->get('doctrine')
            ->getManager();

        return new ORMExecutor(
            $entityManager,
            new ORMPurger($entityManager, ['user'])
        );
    }

    /**
     * @return ContainerAwareLoader
     */
    protected static function getFixtureLoader()
    {
        return new ContainerAwareLoader(
            self::$kernel->getContainer()
        );
    }
}

Testable PHP CSV Streamreader Class inklusive Shunks

class CsvReader implements ReaderInterface
{

    /**
     * shunk size for file import
     */
    private $shunkSize;

    /**
     * @param int $shunkSize
     */
    public function __construct(int $shunkSize)
    {
        $this->shunkSize = $shunkSize;
    }

    /**
     * @param string $file
     * @param callable $callback
     *
     * @return array
     * @throws StorageException
     */
    public function shunkCsvFile(string $file, callable $callback): array
    {
        $file = $this->getFileObject($file);
        $file->setFlags(
            SplFileObject::READ_CSV |
            SplFileObject::SKIP_EMPTY |
            SplFileObject::READ_AHEAD
        );

        $row = 0;
        $data = [];
        if ($file->isFile()) {
            while (!$file->eof()) {
                $line = $file->fgetcsv(';');
                $row++;
                if ($row === 1) {
                    //skip header
                    continue;
                }

                $data[] = $line;

                if (($row % $this->shunkSize) == 0) {
                    $callback($data);
                    $data = [];
                }
            }
        }

        $callback($data);
            
    }

    /**
     * @param string $file
     *
     * @return SplFileObject
     *
     * @codeCoverageIgnore
     */
    protected function getFileObject(string $file): SplFileObject
    {
        return new SplFileObject($file);
    }

Run PHPUnit Unit and Integrations test with different configurations in PHPStorm

If you want to develop unit and integration tests with PHPStorm you can easily bootstrap your application and run your tests. But if you want to develop real unit tests in your local development enviroment without having a database connection or a cache, you need to make sure, that your application is configured differently, when unit tests are running. In this article you will learn how to do that and how to make PHPStorm will automatically recognize which tests/tests suites you want to execute.

Requirement:

Your integration and unit tests are seperated in 2 directories, like:

/tests/unitTests
/tests/integrationsTests

Overview weiterlesen…

PHPUnit @Depends Variablen im @Dataprovider verwenden

Leider ist es zur Zeit nicht möglich für einen PHPUnit Test sowohl einen anderen Test als Vorraussetzung für einen Test zu markieren, damit die Ausführung des Tests im Fehlerfall nicht stattfindet, und gleichzeitig einen Dataprovider für den Test zu verwenden der auf das Ergebnis einen vorherigen Tests zugreift. Das liegt daran, dass Dataprovider vor dem Durchlaufen der Tests initilisiert werden von PHPunit.

Das Problem

class StackTest extends PHPUnit_Framework_TestCase {
    protected static $foo;

    public function provider() { 
        print_r( self::$foo); //does not work
    }

    /**
     * @dataProvider provider
     */
    public function testOne() {
        self::$foo = array();
    }

    /**
     * @depends testOne
     * @dataProvider provider
     */
    public function testTwo( $data ) { 
    }

weiterlesen…