diff --git a/.travis.yml b/.travis.yml
index d6e1dfe..a8ed5b3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,9 +1,25 @@
 language: php
+
 php:
-  - 5.3
+# - 5.3 # requires old distro, see below
+  - 5.4
+  - 5.5
   - 5.6
-  - hhvm
+  - 7.0
+  - 7.1
+  - 7.2
+  - 7.3
+
+# lock distro so future defaults will not break the build
+dist: trusty
+
+matrix:
+  include:
+    - php: 5.3
+      dist: precise
+
 install:
-  - composer install --prefer-source --no-interaction
+  - composer install --no-interaction
+
 script:
-  - phpunit --coverage-text
+  - vendor/bin/phpunit --coverage-text
diff --git a/README.md b/README.md
index 4d8c87b..8dafd30 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,7 @@ Implements UStar (Uniform Standard Tape ARchive) format, introduced by the POSIX
 
 * [Quickstart example](#quickstart-example)
 * [Install](#install)
+* [Tests](#tests)
 * [License](#license)
 * [More](#more)
 
@@ -54,6 +55,25 @@ The recommended way to install this library is [through composer](https://getcom
 }
 ```
 
+This project aims to run on any platform and thus does not require any PHP
+extensions and supports running on legacy PHP 5.3 through current PHP 7+.
+It's *highly recommended to use PHP 7+* for this project.
+
+## Tests
+
+To run the test suite, you first need to clone this repo and then install all
+dependencies [through Composer](https://getcomposer.org):
+
+```bash
+$ composer install
+```
+
+To run the test suite, go to the project root and run:
+
+```bash
+$ php vendor/bin/phpunit
+```
+
 ## License
 
 MIT
diff --git a/composer.json b/composer.json
index b0ce38e..29108ed 100644
--- a/composer.json
+++ b/composer.json
@@ -15,11 +15,15 @@
         "react/stream": "~0.4.0|~0.3.0"
     },
     "require-dev": {
+        "clue/hexdump": "~0.2.0",
         "react/event-loop": "~0.4.0|~0.3.0",
         "react/promise": "~2.0|~1.0",
-        "clue/hexdump": "~0.2.0"
+        "phpunit/phpunit": "^7.0 || ^6.0 || ^5.0 || ^4.8.35"
     },
     "autoload": {
         "psr-4": { "Clue\\React\\Tar\\": "src/" }
+    },
+    "autoload-dev": {
+        "psr-4": { "Clue\\Tests\\React\\Tar\\": "tests/" }
     }
 }
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 4750166..82061b0 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
-<phpunit bootstrap="tests/bootstrap.php"
+<phpunit bootstrap="vendor/autoload.php"
          colors="true"
          convertErrorsToExceptions="true"
          convertNoticesToExceptions="true"
diff --git a/tests/DecoderTest.php b/tests/DecoderTest.php
index 564a8df..1e8785b 100644
--- a/tests/DecoderTest.php
+++ b/tests/DecoderTest.php
@@ -1,5 +1,7 @@
 <?php
 
+namespace Clue\Tests\React\Tar;
+
 use Clue\React\Tar\Decoder;
 
 class DecoderTest extends TestCase
@@ -27,6 +29,9 @@ public function testWritingInvalidDataWillEmitError()
         $this->decoder->write(str_repeat('2', 1024));
     }
 
+    /**
+     * @doesNotPerformAssertions
+     */
     public function testWritingToClosedDecoderDoesNothing()
     {
         $this->decoder->close();
diff --git a/tests/FunctionalDecoderTest.php b/tests/FunctionalDecoderTest.php
index 0b67603..fbde4b1 100644
--- a/tests/FunctionalDecoderTest.php
+++ b/tests/FunctionalDecoderTest.php
@@ -1,5 +1,7 @@
 <?php
 
+namespace Clue\Tests\React\Tar;
+
 use Clue\React\Tar\Decoder;
 use React\EventLoop\StreamSelectLoop;
 use React\Stream\Stream;
@@ -14,6 +16,9 @@ public function setUp()
         $this->loop = new StreamSelectLoop();
     }
 
+    /**
+     * @doesNotPerformAssertions
+     */
     public function testAliceBob()
     {
         $stream = $this->createStream('alice-bob.tar');
@@ -23,6 +28,9 @@ public function testAliceBob()
         $this->loop->run();
     }
 
+    /**
+     * @doesNotPerformAssertions
+     */
     public function testAliceBobWithSmallBufferSize()
     {
         $stream = $this->createStream('alice-bob.tar');
diff --git a/tests/TestCase.php b/tests/TestCase.php
new file mode 100644
index 0000000..82b3cc6
--- /dev/null
+++ b/tests/TestCase.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Clue\Tests\React\Tar;
+
+class TestCase extends \PHPUnit\Framework\TestCase
+{
+    protected function expectCallableOnce()
+    {
+        $mock = $this->createCallableMock();
+        $mock
+            ->expects($this->once())
+            ->method('__invoke');
+
+        return $mock;
+    }
+
+    protected function expectCallableNever()
+    {
+        $mock = $this->createCallableMock();
+        $mock
+            ->expects($this->never())
+            ->method('__invoke');
+
+        return $mock;
+    }
+
+    protected function createCallableMock()
+    {
+        return $this->getMockBuilder('stdClass')->setMethods(array('__invoke'))->getMock();
+    }
+}
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
deleted file mode 100644
index 4f81975..0000000
--- a/tests/bootstrap.php
+++ /dev/null
@@ -1,84 +0,0 @@
-<?php
-
-require_once __DIR__ . '/../vendor/autoload.php';
-
-error_reporting(-1);
-
-class TestCase extends PHPUnit_Framework_TestCase
-{
-    protected function expectCallableOnce()
-    {
-        $mock = $this->createCallableMock();
-        $mock
-            ->expects($this->once())
-            ->method('__invoke');
-
-        return $mock;
-    }
-
-    protected function expectCallableNever()
-    {
-        $mock = $this->createCallableMock();
-        $mock
-            ->expects($this->never())
-            ->method('__invoke');
-
-        return $mock;
-    }
-
-    protected function expectCallableOnceWith($value)
-    {
-        $mock = $this->createCallableMock();
-        $mock
-            ->expects($this->once())
-            ->method('__invoke')
-            ->with($this->equalTo($value));
-
-        return $mock;
-    }
-
-    protected function expectCallableOnceParameter($type)
-    {
-        $mock = $this->createCallableMock();
-        $mock
-            ->expects($this->once())
-            ->method('__invoke')
-            ->with($this->isInstanceOf($type));
-
-        return $mock;
-    }
-
-    /**
-     * @link https://github.com/reactphp/react/blob/master/tests/React/Tests/Socket/TestCase.php (taken from reactphp/react)
-     */
-    protected function createCallableMock()
-    {
-        return $this->getMock('CallableStub');
-    }
-
-    protected function expectPromiseResolve($promise)
-    {
-        $this->assertInstanceOf('React\Promise\PromiseInterface', $promise);
-
-        $promise->then($this->expectCallableOnce(), $this->expectCallableNever());
-
-        return $promise;
-    }
-
-    protected function expectPromiseReject($promise)
-    {
-        $this->assertInstanceOf('React\Promise\PromiseInterface', $promise);
-
-        $promise->then($this->expectCallableNever(), $this->expectCallableOnce());
-
-        return $promise;
-    }
-}
-
-class CallableStub
-{
-    public function __invoke()
-    {
-    }
-}
-
