diff --git a/.gitignore b/.gitignore
index 4cfd7cae..9855f3d1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,16 +25,16 @@ Makefile.in
 /doc/manual/images
 /doc/manual/manual.html
 /doc/manual/manual.pdf
-/tests/.bzr*
-/tests/.git*
-/tests/.hg*
-/tests/nix
-/tests/data
+/t/.bzr*
+/t/.git*
+/t/.hg*
+/t/nix
+/t/data
+/t/jobs/config.nix
 /inst
 hydra-config.h
 hydra-config.h.in
 result
-tests/jobs/config.nix
 outputs
 config
 stamp-h1
diff --git a/.yath.rc b/.yath.rc
new file mode 100644
index 00000000..19bb35af
--- /dev/null
+++ b/.yath.rc
@@ -0,0 +1,2 @@
+[test]
+-I=rel(t/lib)
diff --git a/Makefile.am b/Makefile.am
index ad911b4d..e744cc33 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = src tests doc
+SUBDIRS = src t doc
 BOOTCLEAN_SUBDIRS = $(SUBDIRS)
 DIST_SUBDIRS      = $(SUBDIRS)
 EXTRA_DIST        = hydra-module.nix
diff --git a/configure.ac b/configure.ac
index baff26c2..2fb175c8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -70,8 +70,8 @@ AC_CONFIG_FILES([
   src/lib/Makefile
   src/root/Makefile
   src/script/Makefile
-  tests/Makefile
-  tests/jobs/config.nix
+  t/Makefile
+  t/jobs/config.nix
 ])
 
 AC_CONFIG_COMMANDS([executable-scripts], [])
diff --git a/doc/manual/src/hacking.md b/doc/manual/src/hacking.md
index 6bf447f4..a7904959 100644
--- a/doc/manual/src/hacking.md
+++ b/doc/manual/src/hacking.md
@@ -26,3 +26,21 @@ To build Hydra, you should then do:
 You can run the Hydra web server in your source tree as follows:
 
     $ ./src/script/hydra-server
+
+You can run Hydra's test suite with the following:
+
+    [nix-shell]$ make check
+    [nix-shell]$ # to run as many tests as you have cores:
+    [nix-shell]$ make check YATH_JOB_COUNT=$NIX_BUILD_CORES
+    [nix-shell]$ # or run yath directly:
+    [nix-shell]$ yath test
+    [nix-shell]$ # to run as many tests as you have cores:
+    [nix-shell]$ yath test -j $NIX_BUILD_CORES
+
+When using `yath` instead of `make check`, ensure you have run `make`
+in the root of the repository at least once.
+
+**Warning**: Currently, the tests can fail
+if run with high parallelism [due to an issue in
+`Test::PostgreSQL`](https://github.com/TJC/Test-postgresql/issues/40)
+causing database ports to collide.
diff --git a/flake.nix b/flake.nix
index e7bfb65b..2e2a6574 100644
--- a/flake.nix
+++ b/flake.nix
@@ -320,12 +320,16 @@
             ] ++ lib.optionals stdenv.isLinux [ rpm dpkg cdrkit ] );
 
           shellHook = ''
+            pushd $(git rev-parse --show-toplevel) >/dev/null
+
             PATH=$(pwd)/src/hydra-evaluator:$(pwd)/src/script:$(pwd)/src/hydra-eval-jobs:$(pwd)/src/hydra-queue-runner:$PATH
             PERL5LIB=$(pwd)/src/lib:$PERL5LIB
-            export HYDRA_HOME="src/"
+            export HYDRA_HOME="$(pwd)/src/"
             mkdir -p .hydra-data
             export HYDRA_DATA="$(pwd)/.hydra-data"
             export HYDRA_DBI='dbi:Pg:dbname=hydra;host=localhost;port=64444'
+
+            popd >/dev/null
           '';
 
           preConfigure = "autoreconf -vfi";
@@ -416,7 +420,7 @@
                         su - hydra -c "hydra-create-user root --email-address 'alice@example.org' --password foobar --role admin"
                         mkdir /run/jobset /tmp/nix
                         chmod 755 /run/jobset /tmp/nix
-                        cp ${./tests/api-test.nix} /run/jobset/default.nix
+                        cp ${./t/api-test.nix} /run/jobset/default.nix
                         chmod 644 /run/jobset/default.nix
                         chown -R hydra /run/jobset /tmp/nix
                 """
@@ -428,7 +432,7 @@
 
                 # Run the API tests.
                 machine.succeed(
-                    "su - hydra -c 'perl -I ${pkgs.hydra.perlDeps}/lib/perl5/site_perl ${./tests/api-test.pl}' >&2"
+                    "su - hydra -c 'perl -I ${pkgs.hydra.perlDeps}/lib/perl5/site_perl ${./t/api-test.pl}' >&2"
                 )
               '';
         };
@@ -455,7 +459,7 @@
                       su - hydra -c "hydra-create-user root --email-address 'alice@example.org' --password foobar --role admin"
                       mkdir /run/jobset
                       chmod 755 /run/jobset
-                      cp ${./tests/api-test.nix} /run/jobset/default.nix
+                      cp ${./t/api-test.nix} /run/jobset/default.nix
                       chmod 644 /run/jobset/default.nix
                       chown -R hydra /run/jobset
               """
@@ -477,7 +481,7 @@
 
               # Setup the project and jobset
               machine.succeed(
-                  "su - hydra -c 'perl -I ${pkgs.hydra.perlDeps}/lib/perl5/site_perl ${./tests/setup-notifications-jobset.pl}' >&2"
+                  "su - hydra -c 'perl -I ${pkgs.hydra.perlDeps}/lib/perl5/site_perl ${./t/setup-notifications-jobset.pl}' >&2"
               )
 
               # Wait until hydra has build the job and
diff --git a/tests/Makefile.am b/t/Makefile.am
similarity index 100%
rename from tests/Makefile.am
rename to t/Makefile.am
diff --git a/tests/api-test.nix b/t/api-test.nix
similarity index 100%
rename from tests/api-test.nix
rename to t/api-test.nix
diff --git a/tests/api-test.pl b/t/api-test.pl
similarity index 100%
rename from tests/api-test.pl
rename to t/api-test.pl
diff --git a/tests/build-products.t b/t/build-products.t
similarity index 100%
rename from tests/build-products.t
rename to t/build-products.t
diff --git a/tests/evaluate-basic.t b/t/evaluate-basic.t
similarity index 100%
rename from tests/evaluate-basic.t
rename to t/evaluate-basic.t
diff --git a/tests/evaluate-dependent-jobsets.t b/t/evaluate-dependent-jobsets.t
similarity index 100%
rename from tests/evaluate-dependent-jobsets.t
rename to t/evaluate-dependent-jobsets.t
diff --git a/tests/input-types/bzr-checkout.t b/t/input-types/bzr-checkout.t
similarity index 100%
rename from tests/input-types/bzr-checkout.t
rename to t/input-types/bzr-checkout.t
diff --git a/tests/input-types/bzr.t b/t/input-types/bzr.t
similarity index 100%
rename from tests/input-types/bzr.t
rename to t/input-types/bzr.t
diff --git a/tests/input-types/darcs.t b/t/input-types/darcs.t
similarity index 100%
rename from tests/input-types/darcs.t
rename to t/input-types/darcs.t
diff --git a/tests/input-types/deepgit.t b/t/input-types/deepgit.t
similarity index 100%
rename from tests/input-types/deepgit.t
rename to t/input-types/deepgit.t
diff --git a/tests/input-types/git-rev.t b/t/input-types/git-rev.t
similarity index 100%
rename from tests/input-types/git-rev.t
rename to t/input-types/git-rev.t
diff --git a/tests/input-types/git.t b/t/input-types/git.t
similarity index 100%
rename from tests/input-types/git.t
rename to t/input-types/git.t
diff --git a/tests/input-types/hg.t b/t/input-types/hg.t
similarity index 100%
rename from tests/input-types/hg.t
rename to t/input-types/hg.t
diff --git a/tests/input-types/svn-checkout.t b/t/input-types/svn-checkout.t
similarity index 100%
rename from tests/input-types/svn-checkout.t
rename to t/input-types/svn-checkout.t
diff --git a/tests/input-types/svn.t b/t/input-types/svn.t
similarity index 100%
rename from tests/input-types/svn.t
rename to t/input-types/svn.t
diff --git a/tests/jobs/basic.nix b/t/jobs/basic.nix
similarity index 100%
rename from tests/jobs/basic.nix
rename to t/jobs/basic.nix
diff --git a/tests/jobs/build-output-as-input.nix b/t/jobs/build-output-as-input.nix
similarity index 100%
rename from tests/jobs/build-output-as-input.nix
rename to t/jobs/build-output-as-input.nix
diff --git a/tests/jobs/build-product-simple.sh b/t/jobs/build-product-simple.sh
similarity index 100%
rename from tests/jobs/build-product-simple.sh
rename to t/jobs/build-product-simple.sh
diff --git a/tests/jobs/build-product-with-spaces.sh b/t/jobs/build-product-with-spaces.sh
similarity index 100%
rename from tests/jobs/build-product-with-spaces.sh
rename to t/jobs/build-product-with-spaces.sh
diff --git a/tests/jobs/build-products.nix b/t/jobs/build-products.nix
similarity index 100%
rename from tests/jobs/build-products.nix
rename to t/jobs/build-products.nix
diff --git a/tests/jobs/bzr-checkout-input.nix b/t/jobs/bzr-checkout-input.nix
similarity index 100%
rename from tests/jobs/bzr-checkout-input.nix
rename to t/jobs/bzr-checkout-input.nix
diff --git a/tests/jobs/bzr-checkout-update.sh b/t/jobs/bzr-checkout-update.sh
similarity index 100%
rename from tests/jobs/bzr-checkout-update.sh
rename to t/jobs/bzr-checkout-update.sh
diff --git a/tests/jobs/bzr-input.nix b/t/jobs/bzr-input.nix
similarity index 100%
rename from tests/jobs/bzr-input.nix
rename to t/jobs/bzr-input.nix
diff --git a/tests/jobs/bzr-update.sh b/t/jobs/bzr-update.sh
similarity index 100%
rename from tests/jobs/bzr-update.sh
rename to t/jobs/bzr-update.sh
diff --git a/tests/jobs/config.nix.in b/t/jobs/config.nix.in
similarity index 100%
rename from tests/jobs/config.nix.in
rename to t/jobs/config.nix.in
diff --git a/tests/jobs/darcs-input.nix b/t/jobs/darcs-input.nix
similarity index 100%
rename from tests/jobs/darcs-input.nix
rename to t/jobs/darcs-input.nix
diff --git a/tests/jobs/darcs-update.sh b/t/jobs/darcs-update.sh
similarity index 100%
rename from tests/jobs/darcs-update.sh
rename to t/jobs/darcs-update.sh
diff --git a/tests/jobs/deepgit-builder.sh b/t/jobs/deepgit-builder.sh
similarity index 100%
rename from tests/jobs/deepgit-builder.sh
rename to t/jobs/deepgit-builder.sh
diff --git a/tests/jobs/deepgit-input.nix b/t/jobs/deepgit-input.nix
similarity index 100%
rename from tests/jobs/deepgit-input.nix
rename to t/jobs/deepgit-input.nix
diff --git a/tests/jobs/empty-dir-builder.sh b/t/jobs/empty-dir-builder.sh
similarity index 100%
rename from tests/jobs/empty-dir-builder.sh
rename to t/jobs/empty-dir-builder.sh
diff --git a/tests/jobs/fail.sh b/t/jobs/fail.sh
similarity index 100%
rename from tests/jobs/fail.sh
rename to t/jobs/fail.sh
diff --git a/tests/jobs/git-input.nix b/t/jobs/git-input.nix
similarity index 100%
rename from tests/jobs/git-input.nix
rename to t/jobs/git-input.nix
diff --git a/tests/jobs/git-rev-input.nix b/t/jobs/git-rev-input.nix
similarity index 100%
rename from tests/jobs/git-rev-input.nix
rename to t/jobs/git-rev-input.nix
diff --git a/tests/jobs/git-rev-update.sh b/t/jobs/git-rev-update.sh
similarity index 100%
rename from tests/jobs/git-rev-update.sh
rename to t/jobs/git-rev-update.sh
diff --git a/tests/jobs/git-update.sh b/t/jobs/git-update.sh
similarity index 100%
rename from tests/jobs/git-update.sh
rename to t/jobs/git-update.sh
diff --git a/tests/jobs/hg-input.nix b/t/jobs/hg-input.nix
similarity index 100%
rename from tests/jobs/hg-input.nix
rename to t/jobs/hg-input.nix
diff --git a/tests/jobs/hg-update.sh b/t/jobs/hg-update.sh
similarity index 100%
rename from tests/jobs/hg-update.sh
rename to t/jobs/hg-update.sh
diff --git a/tests/jobs/runcommand.nix b/t/jobs/runcommand.nix
similarity index 100%
rename from tests/jobs/runcommand.nix
rename to t/jobs/runcommand.nix
diff --git a/tests/jobs/scm-builder.sh b/t/jobs/scm-builder.sh
similarity index 100%
rename from tests/jobs/scm-builder.sh
rename to t/jobs/scm-builder.sh
diff --git a/tests/jobs/succeed-with-failed.sh b/t/jobs/succeed-with-failed.sh
similarity index 100%
rename from tests/jobs/succeed-with-failed.sh
rename to t/jobs/succeed-with-failed.sh
diff --git a/tests/jobs/svn-checkout-input.nix b/t/jobs/svn-checkout-input.nix
similarity index 100%
rename from tests/jobs/svn-checkout-input.nix
rename to t/jobs/svn-checkout-input.nix
diff --git a/tests/jobs/svn-checkout-update.sh b/t/jobs/svn-checkout-update.sh
similarity index 100%
rename from tests/jobs/svn-checkout-update.sh
rename to t/jobs/svn-checkout-update.sh
diff --git a/tests/jobs/svn-input.nix b/t/jobs/svn-input.nix
similarity index 100%
rename from tests/jobs/svn-input.nix
rename to t/jobs/svn-input.nix
diff --git a/tests/jobs/svn-update.sh b/t/jobs/svn-update.sh
similarity index 100%
rename from tests/jobs/svn-update.sh
rename to t/jobs/svn-update.sh
diff --git a/tests/lib/Setup.pm b/t/lib/Setup.pm
similarity index 100%
rename from tests/lib/Setup.pm
rename to t/lib/Setup.pm
diff --git a/tests/lib/TestScmInput.pm b/t/lib/TestScmInput.pm
similarity index 100%
rename from tests/lib/TestScmInput.pm
rename to t/lib/TestScmInput.pm
diff --git a/tests/plugins/runcommand.t b/t/plugins/runcommand.t
similarity index 100%
rename from tests/plugins/runcommand.t
rename to t/plugins/runcommand.t
diff --git a/tests/s3-backup-test.config b/t/s3-backup-test.config
similarity index 100%
rename from tests/s3-backup-test.config
rename to t/s3-backup-test.config
diff --git a/tests/s3-backup-test.pl b/t/s3-backup-test.pl
similarity index 100%
rename from tests/s3-backup-test.pl
rename to t/s3-backup-test.pl
diff --git a/tests/setup-notifications-jobset.pl b/t/setup-notifications-jobset.pl
similarity index 100%
rename from tests/setup-notifications-jobset.pl
rename to t/setup-notifications-jobset.pl
diff --git a/tests/test.pl b/t/test.pl
similarity index 100%
rename from tests/test.pl
rename to t/test.pl