diff --git a/tests/BuiltInServer.php b/tests/BuiltInServer.php
deleted file mode 100644
index 338e2d92e06df35efbd0e802030e1558dca0eace..0000000000000000000000000000000000000000
--- a/tests/BuiltInServer.php
+++ /dev/null
@@ -1,233 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace SimpleSAML\Test;
-
-use SimpleSAML\Utils\System;
-
-/**
- * An extremely simple class to start and stop PHP's built-in server, with the possibility to specify the document
- * root and the "router" file to run for every request.
- *
- * @author Jaime PĂ©rez Crespo <jaime.perez@uninett.no>
- * @package SimpleSAMLphp
- */
-
-class BuiltInServer
-{
-    /**
-     * The PID of the running server.
-     *
-     * @var int
-     */
-    protected $pid = 0;
-
-    /**
-     * The address (host:port) where the server is listening for connections after being started.
-     *
-     * @var string
-     */
-    protected $address = 'example.org';
-
-    /**
-     * The name of a "router" file to run for every request performed to this server.
-     *
-     * @var string
-     */
-    protected $router = '';
-
-    /**
-     * The document root of the server.
-     *
-     * @var string
-     */
-    protected $docroot;
-
-
-    /**
-     * BuiltInServer constructor.
-     *
-     * @param string|null $router The name of a "router" file to run first for every request performed to this server.
-     * @param string|null $docroot The document root to use when starting the server.
-     *
-     * @see http://php.net/manual/en/features.commandline.webserver.php
-     */
-    public function __construct($router = null, $docroot = null)
-    {
-        if (!is_null($router)) {
-            $this->setRouter($router);
-        }
-
-        if (!is_null($docroot)) {
-            $this->docroot = $docroot;
-        } else {
-            $this->docroot = dirname(dirname(__FILE__)) . '/www/';
-        }
-
-        // Rationalize docroot
-        $this->docroot = str_replace('\\', '/', $this->docroot);
-        $this->docroot = rtrim($this->docroot, '/');
-    }
-
-
-    /**
-     * Start the built-in server in a random port.
-     *
-     * This method will wait up to 5 seconds for the server to start. When it returns an address, it is guaranteed that
-     * the server has started and is listening for connections. If it returns the default value on the other hand,
-     * there will be no guarantee that the server started properly.
-     *
-     * @return string The address where the server is listening for connections, or false if the server failed to start
-     * for some reason.
-     *
-     * @todo This method should be resilient to clashes in the randomly-picked port number.
-     */
-    public function start()
-    {
-        $port = mt_rand(1025, 65535);
-        $this->address = 'localhost:' . $port;
-
-        if (System::getOS() === System::WINDOWS) {
-            $command = sprintf(
-                'powershell $proc = start-process php -ArgumentList (\'-S %s\', \'-t %s\', \'%s\') '
-                    . '-Passthru; Write-output $proc.Id;',
-                $this->address,
-                $this->docroot,
-                $this->router
-            );
-        } else {
-            $command = sprintf(
-                'php -S %s -t %s %s >> /dev/null 2>&1 & echo $!',
-                $this->address,
-                $this->docroot,
-                $this->router
-            );
-        }
-
-        // execute the command and store the process ID
-        $output = [];
-        exec($command, $output);
-        $this->pid = intval($output[0]);
-
-        // wait until it's listening for connections to avoid race conditions
-        $start = microtime(true);
-        do {
-            $sock = @fsockopen('localhost', $port, $errno, $errstr, 10);
-            if ($sock === false) {
-                // set a 5 secs timeout waiting for the server to start
-                if (microtime(true) > $start + 5) {
-                    $this->pid = 0; // signal failure
-                    break;
-                }
-            }
-        } while ($sock === false);
-
-        if ($sock !== false) {
-            fclose($sock);
-        }
-
-        return $this->address;
-    }
-
-
-    /**
-     * Stop the built-in server.
-     * @return void
-     */
-    public function stop()
-    {
-        if ($this->pid === 0) {
-            return;
-        } elseif (System::getOS() === System::WINDOWS) {
-            exec('taskkill /PID ' . $this->pid);
-        } else {
-            exec('kill ' . $this->pid);
-        }
-        $this->pid = 0;
-    }
-
-
-    /**
-     * Get the PID of the running server.
-     *
-     * @return int The PID of the server, or 0 if the server was not started.
-     */
-    public function getPid()
-    {
-        return $this->pid;
-    }
-
-
-    /**
-     * Get the name of the "router" file.
-     *
-     * @return string The name of the "router" file.
-     */
-    public function getRouter()
-    {
-        return $this->router;
-    }
-
-
-    /**
-     * Set the "router" file.
-     *
-     * @param string $router The name of a "router" file to use when starting the server.
-     * @return void
-     */
-    public function setRouter($router)
-    {
-        $file = dirname(dirname(__FILE__)) . '/tests/routers/' . $router . '.php';
-        if (!file_exists($file)) {
-            throw new \InvalidArgumentException('Unknown router "' . $router . '".');
-        }
-        $this->router = $file;
-    }
-
-
-    /**
-     * This function performs an HTTP GET request to the built-in server.
-     *
-     * @param string $query The query to perform.
-     * @param array $parameters An array (can be empty) with parameters for the requested URI.
-     * @param array $curlopts An array (can be empty) with options for cURL.
-     *
-     * @return array The response obtained from the built-in server.
-     */
-    public function get($query, $parameters, $curlopts = [])
-    {
-        $ch = curl_init();
-        $url = 'http://' . $this->address . $query;
-        $url .= (!empty($parameters)) ? '?' . http_build_query($parameters) : '';
-        curl_setopt_array($ch, [
-            CURLOPT_URL => $url,
-            CURLOPT_RETURNTRANSFER => 1,
-            CURLOPT_HEADER => 1,
-        ]);
-        curl_setopt_array($ch, $curlopts);
-
-        /** @psalm-var array|false $resp  RETURNTRANSFER was set to true */
-        $resp = curl_exec($ch);
-
-        if ($resp === false) {
-            throw new \Exception("Unable to contact: " . $url);
-        }
-
-        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
-        list($header, $body) = explode("\r\n\r\n", $resp, 2);
-        $raw_headers = explode("\r\n", $header);
-        array_shift($raw_headers);
-        $headers = [];
-        foreach ($raw_headers as $header) {
-            list($name, $value) = explode(':', $header, 2);
-            $headers[trim($name)] = trim($value);
-        }
-        curl_close($ch);
-        return [
-            'code' => $code,
-            'headers' => $headers,
-            'body' => $body,
-        ];
-    }
-}
diff --git a/tests/routers/configLoader.php b/tests/routers/configLoader.php
deleted file mode 100644
index b148e80bac67ab9c3380178e28d973aa1dafb2a0..0000000000000000000000000000000000000000
--- a/tests/routers/configLoader.php
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/*
- * This "router" (a script that's executed for every request received by PHP's built-in web server) will look
- * for a file in the system's temporary directory, with the PID of the current process as its name, and the
- * '.lock' extension. If the file exists, it will try to include it and preload SimpleSAMLphp's configuration with
- * the $config array defined in that file.
- * This is useful to configure SimpleSAMLphp dynamically when running inside the built-in server, so that
- * we can test different configurations without the need to keep a structure of files.
- *
- * In order to use it:
- *
- * 1. Create an array with the SimpleSAMLphp configuration you would like to use.
- * 2. Start the built-in server passing "configLoader" as the first parameter to the constructor:
- *      $server = new BuiltInServer('configLoader');
- *      $addr = $server->start();
- * 3. Get the PID of the server once it has started:
- *      $pid = $server->getPid();
- * 4. Build the path to the file that this script will use:
- *      $file = sys_get_temp_dir().'/'.$pid.'.lock';
- * 5. Dump the configuration array to the file:
- *      file_put_contents("<?php\n\$config = ".var_export($config, true).";\n");
- * 6. Make a request to the server:
- *      $server->get($query, $parameters);
- * 7. Remove the temporary file when done:
- *      unlink($file);
- */
-
-include_once(sys_get_temp_dir() . '/' . getmypid() . '.lock');
-
-// load SimpleSAMLphp's autoloader
-require_once(dirname(__FILE__) . '/../../vendor/autoload.php');
-
-// initialize configuration
-if (isset($config)) {
-    \SimpleSAML\Configuration::loadFromArray($config, '[ARRAY]', 'simplesaml');
-}
-
-// let the script proceed
-// see: http://php.net/manual/en/features.commandline.webserver.php
-return false;
diff --git a/tests/www/IndexTest.php b/tests/www/IndexTest.php
index 860324a70187beba7a03c23b4624dd887a576e75..1985d838872fd8ab2fe08583285d41a3d80be5a1 100644
--- a/tests/www/IndexTest.php
+++ b/tests/www/IndexTest.php
@@ -5,7 +5,7 @@ declare(strict_types=1);
 namespace SimpleSAML\Test\Web;
 
 use PHPUnit\Framework\TestCase;
-use SimpleSAML\Test\BuiltInServer;
+use SimpleSAML\TestUtils\BuiltInServer;
 
 /**
  * Simple test for the www/index.php script.
@@ -18,7 +18,7 @@ use SimpleSAML\Test\BuiltInServer;
 class IndexTest extends TestCase
 {
     /**
-     * @var \SimpleSAML\Test\BuiltInServer
+     * @var \SimpleSAML\TestUtils\BuiltInServer
      */
     protected $server;
 
@@ -57,7 +57,7 @@ class IndexTest extends TestCase
      * @param array $config
      * @return void
      */
-    protected function updateConfig(array $config)
+    protected function updateConfig(array $config): void
     {
         @unlink($this->shared_file);
         $config = "<?php\n\$config = " . var_export($config, true) . ";\n";
@@ -69,7 +69,7 @@ class IndexTest extends TestCase
      * A simple test to make sure the index.php file redirects appropriately to the right URL.
      * @return void
      */
-    public function testRedirection()
+    public function testRedirection(): void
     {
         // test most basic redirection
         $this->updateConfig([