diff --git a/scripts/maint/practracker/test_practracker.sh b/scripts/maint/practracker/test_practracker.sh
index 207a5ceded9a6ee5e3d34c644d3e38f5f03b04ed..afc267a00041e92957a58cf20317936238b63aa6 100755
--- a/scripts/maint/practracker/test_practracker.sh
+++ b/scripts/maint/practracker/test_practracker.sh
@@ -1,5 +1,8 @@
 #!/bin/sh
 
+# Fail if any subprocess fails unexpectedly
+set -e
+
 umask 077
 unset TOR_DISABLE_PRACTRACKER
 
@@ -16,6 +19,11 @@ if test "${PRACTRACKER_DIR}" = "" ||
     PRACTRACKER_DIR=$(dirname "$0")
 fi
 
+# Change to the tor directory, and canonicalise PRACTRACKER_DIR,
+# so paths in practracker output are consistent, even in out-of-tree builds
+cd "${PRACTRACKER_DIR}"/../../..
+PRACTRACKER_DIR="scripts/maint/practracker"
+
 TMPDIR="$(mktemp -d -t pracktracker.test.XXXXXX)"
 if test -z "${TMPDIR}" || test ! -d "${TMPDIR}" ; then
     echo >&2 "mktemp failed."
@@ -33,11 +41,11 @@ run_practracker() {
         --max-h-include-count=0 \
         --max-include-count=0 \
         --terse \
-        "${DATA}/" "$@";
+        "${DATA}/" "$@" || echo "practracker exit status: $?"
 }
 compare() {
     # we can't use cmp because we need to use -b for windows
-    diff -b -u "$@" > "${TMPDIR}/test-diff"
+    diff -b -u "$@" > "${TMPDIR}/test-diff" || true
     if test -z "$(cat "${TMPDIR}"/test-diff)"; then
         echo "OK"
     else
@@ -49,22 +57,28 @@ compare() {
 
 echo "unit tests:"
 
-"${PYTHON:-python}" "${PRACTRACKER_DIR}/practracker_tests.py" || exit 1
+"${PYTHON:-python}" "${PRACTRACKER_DIR}/practracker_tests.py"
 
 echo "ex0:"
 
-run_practracker --exceptions "${DATA}/ex0.txt" > "${TMPDIR}/ex0-received.txt"
+run_practracker --exceptions "${DATA}/ex0.txt" \
+                > "${TMPDIR}/ex0-received.txt" 2>&1
 
-compare "${TMPDIR}/ex0-received.txt" "${DATA}/ex0-expected.txt"
+compare "${TMPDIR}/ex0-received.txt" \
+        "${DATA}/ex0-expected.txt"
 
 echo "ex1:"
 
-run_practracker --exceptions "${DATA}/ex1.txt" > "${TMPDIR}/ex1-received.txt"
+run_practracker --exceptions "${DATA}/ex1.txt" \
+                > "${TMPDIR}/ex1-received.txt" 2>&1
 
-compare "${TMPDIR}/ex1-received.txt" "${DATA}/ex1-expected.txt"
+compare "${TMPDIR}/ex1-received.txt" \
+        "${DATA}/ex1-expected.txt"
 
 echo "ex1.overbroad:"
 
-run_practracker --exceptions "${DATA}/ex1.txt" --list-overbroad > "${TMPDIR}/ex1-overbroad-received.txt"
+run_practracker --exceptions "${DATA}/ex1.txt" --list-overbroad \
+                > "${TMPDIR}/ex1-overbroad-received.txt" 2>&1
 
-compare "${TMPDIR}/ex1-overbroad-received.txt" "${DATA}/ex1-overbroad-expected.txt"
+compare "${TMPDIR}/ex1-overbroad-received.txt" \
+        "${DATA}/ex1-overbroad-expected.txt"
diff --git a/scripts/maint/practracker/testdata/ex0-expected.txt b/scripts/maint/practracker/testdata/ex0-expected.txt
index 502005edb19f752c2e44b78081204d47dd7cc460..c9fb83bac3ab27fdc9ac827ba4c819203a5bcc31 100644
--- a/scripts/maint/practracker/testdata/ex0-expected.txt
+++ b/scripts/maint/practracker/testdata/ex0-expected.txt
@@ -1,3 +1,4 @@
+Unusual pattern permitted.h in scripts/maint/practracker/testdata
 problem file-size a.c 41
 problem include-count a.c 6
 problem function-size a.c:i_am_a_function() 9
@@ -9,3 +10,4 @@ problem function-size b.c:bar() 5
 problem file-size header.h 8
 problem include-count header.h 4
 problem dependency-violation header.h 3
+practracker exit status: 11
diff --git a/scripts/maint/practracker/testdata/ex1-expected.txt b/scripts/maint/practracker/testdata/ex1-expected.txt
index 58140a4d9a1a4aa5f8bb2404016c71ade9b92bb6..2713338ae4e51b417d4d6a69151cfa46eb6dbc05 100644
--- a/scripts/maint/practracker/testdata/ex1-expected.txt
+++ b/scripts/maint/practracker/testdata/ex1-expected.txt
@@ -1,3 +1,5 @@
+Unusual pattern permitted.h in scripts/maint/practracker/testdata
 problem function-size a.c:i_am_a_function() 9
 (warning) problem function-size a.c:another_function() 12
 problem function-size b.c:foo() 4
+practracker exit status: 2
diff --git a/scripts/maint/practracker/testdata/ex1-overbroad-expected.txt b/scripts/maint/practracker/testdata/ex1-overbroad-expected.txt
index b757202dae4edf7b646573be731244edee40d267..5ca480dc045d33378e8df2732c8a4750b52eeecb 100644
--- a/scripts/maint/practracker/testdata/ex1-overbroad-expected.txt
+++ b/scripts/maint/practracker/testdata/ex1-overbroad-expected.txt
@@ -1,2 +1,4 @@
+Unusual pattern permitted.h in scripts/maint/practracker/testdata
 problem file-size a.c 45 -> 41
 problem file-size z.c 100 -> 0
+practracker exit status: 3