How to Instantly Migrate Nette\Tester to PHPUnit

We had 🍺 after PHP meetup in Prague and Tomas asked me:
"We don't use Nette, but we still have many tests in Tester. Can Rector migrate them to PHPUnit?"
"Hold my 🍺"

If you don't know Tester, is a PHP unit test framework created in the Czech Republic.

In the last post we looked on instant migration of PhpSpec to PHPUnit.

PhpSpec has a different architecture than PHPUnit - e.g.

This has a huge influence on the code, so it took a week to cover these differences in migration path.

How does Tester compare to PHPUnit?

In the last post we looked at absolute downloads and trends of 3 PHP unit test frameworks:

Putting numbers and trends aside - this is about your needs. Do you need to change from Doctrine to Eloquent? From Symfony 4.2 to Laravel 5.8? From Symfony to Nette? Go for it, Rector will help you with the boring PHP work you'd love to skip.

The guy in the pub that night needed this, so... challenge accepted!

Single Test Case

Luckily, Tester and PHPUnit are like twins:

So all we need to do is rename a few methods? There are still a few gotchas:

Luckily, last 2 operations are subtractions, so we can just remove them.

And the Result?


 namespace App\Tests;

 use App\Entity\SomeObject;
-use Tester\Assert;
-use Tester\TestCase;

-require_once __DIR__ . '/bootstrap.php';

-class ExpensiveObjectTest extends TestCase
+class ExpensiveObjectTest extends \PHPUnit\Framework\TestCase
     public function testSwitches()
-        Assert::false(5);
+        $this->assertFalse(5);

-        Assert::falsey('value', 'some messsage');
+        $this->assertFalse((bool) 'value', 'some messsage');

-        Assert::truthy(true);
+        $this->assertTrue(true);

     public function testTypes()
         $value = 'x';
-        Assert::type('array', $value);
+        $this->assertIsArray($value);

-        Assert::type(SomeObject::class, $value);
+        $this->assertInstanceOf(SomeObject::class, $value);

     public function testException()
         $someObject = new SomeObject;
-        Assert::exception(function () use ($someObject) {
-            $someObject->setPrice('twenty dollars');
-        }, InvalidArgumentException::class, 'Price should be string, you know');
+        $this->expectException(InvalidArgumentException::class);
+        $this->expectExceptionMessage('Price should be string, you know');
+        $someObject->setPrice('twenty dollars');

+    /**
+     * @doesNotPerformAssertions
+     */
     public function testNoError()
-        Assert::noError(function () {
-             new SomeObject(25)
-        });
+        new SomeObject(25);

-(new ExpensiveObjectTest())->run();

How to Instantly Migrate from Nette\Tester to PHPUnit?

composer require rector/rector --dev
vendor/bin/rector process spec --set nette-tetser-to-phpunit

Rector doesn't replace you, it helps you - so take few minutes to polish the details that Rectors missed and send the PR to your project

But if it's something daunting, create an issue - there might be a way to automate it.

Happy coding!