[Libguestfs] [PATCH 3/3] tests: Extend $TEST_FUNCTIONS with predefined functions for skipping tests etc.

Richard W.M. Jones rjones at redhat.com
Mon Feb 20 20:20:13 UTC 2017


Apply this change across all the shell scripts containing tests.

Additionally this defines the environment variables $abs_srcdir,
$abs_builddir, $top_srcdir, $top_builddir, $abs_top_srcdir and
$abs_top_builddir which can now be used throughout test scripts.
---
 align/test-virt-alignment-scan-docs.sh             |   6 +-
 align/test-virt-alignment-scan-guests.sh           |  11 +-
 align/test-virt-alignment-scan.sh                  |   3 +-
 bash/test-complete-in-script.sh                    |   9 +-
 builder/test-console.sh                            |  29 +--
 builder/test-virt-builder-docs.sh                  |  10 +-
 builder/test-virt-builder-list-simplestreams.sh    |   4 +-
 builder/test-virt-builder-list.sh                  |   4 +-
 builder/test-virt-builder-planner.sh               |  21 +-
 builder/test-virt-builder.sh                       |   9 +-
 cat/test-docs.sh                                   |  16 +-
 cat/test-virt-cat.sh                               |   4 +-
 cat/test-virt-filesystems.sh                       |   4 +-
 cat/test-virt-log.sh                               |   4 +-
 cat/test-virt-ls.sh                                |   4 +-
 cat/test-virt-tail.sh                              |   9 +-
 customize/test-firstboot.sh                        |  28 +--
 customize/test-settings.sh                         |  28 +--
 customize/test-virt-customize-docs.sh              |   9 +-
 customize/test-virt-customize.sh                   |  15 +-
 df/test-virt-df-docs.sh                            |   5 +-
 df/test-virt-df-guests.sh                          |  10 +-
 df/test-virt-df.sh                                 |   3 +-
 dib/test-virt-dib-docs.sh                          |   5 +-
 diff/test-virt-diff-docs.sh                        |   5 +-
 diff/test-virt-diff.sh                             |  14 +-
 docs/guestfs-hacking.pod                           |   4 +-
 edit/test-virt-edit-docs.sh                        |   5 +-
 edit/test-virt-edit.sh                             |   9 +-
 fish/test-a.sh                                     |   3 +
 fish/test-add-domain.sh                            |  19 +-
 fish/test-add-uri.sh                               |   5 +-
 fish/test-alloc.sh                                 |   3 +
 fish/test-copy.sh                                  |   7 +-
 fish/test-d.sh                                     |  15 +-
 fish/test-docs.sh                                  |   6 +-
 fish/test-edit.sh                                  |   7 +-
 fish/test-escapes.sh                               |   3 +
 fish/test-events.sh                                |   3 +
 fish/test-file-attrs.sh                            |   4 +-
 fish/test-find0.sh                                 |   8 +-
 fish/test-glob.sh                                  |   3 +
 fish/test-inspect.sh                               |   9 +-
 fish/test-invalid-params.sh                        |   3 +
 fish/test-mount-local.sh                           |  15 +-
 fish/test-read-file.sh                             |  10 +-
 fish/test-remote-events.sh                         |   3 +
 fish/test-remote.sh                                |   3 +
 fish/test-reopen.sh                                |   3 +
 fish/test-run.sh                                   |   8 +-
 fish/test-stringlist.sh                            |   3 +
 fish/test-tilde.sh                                 |   3 +
 fish/test-upload-to-dir.sh                         |   9 +-
 format/test-virt-format-docs.sh                    |   6 +-
 format/test-virt-format.sh                         |   6 +-
 fuse/test-docs.sh                                  |   8 +-
 fuse/test-fuse-umount-race.sh                      |  33 +--
 fuse/test-guestunmount-not-mounted.sh              |  24 +--
 generator/fish.ml                                  |   3 +
 get-kernel/test-virt-get-kernel-docs.sh            |   6 +-
 inspector/test-virt-inspector-docs.sh              |   6 +-
 inspector/test-virt-inspector.sh                   |   8 +-
 inspector/test-xmllint.sh.in                       |   4 +-
 make-fs/test-virt-make-fs-docs.sh                  |   6 +-
 make-fs/test-virt-make-fs.sh                       |   4 +-
 mllib/test-getopt.sh                               |   3 +
 p2v/test-virt-p2v-cmdline.sh                       |   8 +-
 p2v/test-virt-p2v-docs.sh                          |   6 +-
 p2v/test-virt-p2v-nbdkit.sh                        |  37 +---
 p2v/test-virt-p2v-pxe.sh                           |  39 +---
 p2v/test-virt-p2v.sh                               |  31 +--
 rescue/test-virt-rescue-docs.sh                    |   6 +-
 rescue/test-virt-rescue-suggest.sh                 |  10 +-
 resize/test-virt-resize-docs.sh                    |   6 +-
 sparsify/test-virt-sparsify-docs.sh                |   8 +-
 ...st-virt-sparsify-in-place-fstrim-unsupported.sh |  14 +-
 sparsify/test-virt-sparsify-in-place.sh            |  14 +-
 sparsify/test-virt-sparsify.sh                     |   9 +-
 subdir-rules.mk                                    |  18 +-
 sysprep/Makefile.am                                |   3 -
 sysprep/test-virt-sysprep-backup-files.sh          |  24 +--
 sysprep/test-virt-sysprep-docs.sh                  |   6 +-
 sysprep/test-virt-sysprep-passwords.sh             |  21 +-
 sysprep/test-virt-sysprep-script.sh                |  25 ++-
 sysprep/test-virt-sysprep.sh                       |   7 +-
 tests/9p/Makefile.am                               |   2 +-
 tests/9p/test-9p.sh                                |  13 +-
 tests/btrfs/test-btrfs-devices.sh                  |  22 +-
 tests/btrfs/test-btrfs-replace.sh                  |  16 +-
 tests/create/test-disk-create.sh                   |   8 +-
 tests/disks/Makefile.am                            |   2 -
 tests/disks/test-qemu-drive-libvirt.sh             |  24 +--
 tests/disks/test-qemu-drive.sh                     |   9 +-
 tests/luks/test-luks-list.sh                       |  13 +-
 tests/luks/test-luks.sh                            |  13 +-
 tests/lvm/test-lvm-filtering.sh                    |   6 +-
 tests/md/test-inspect-fstab-md.sh                  |  13 +-
 tests/md/test-inspect-fstab.sh                     |  14 +-
 tests/md/test-list-filesystems.sh                  |   6 +-
 tests/md/test-list-md-devices.sh                   |   6 +-
 tests/md/test-mdadm.sh                             |   6 +-
 tests/mountable/test-mountable-inspect.sh          |  23 +-
 tests/network/test-network.sh                      |  14 +-
 tests/ntfs/test-ntfscat.sh                         |  24 +--
 tests/ntfs/test-ntfsclone.sh                       |  22 +-
 tests/protocol/test-both-ends-cancel.sh            |   3 +
 .../test-cancellation-download-librarycancels.sh   |   3 +
 .../test-cancellation-upload-daemoncancels.sh      |   3 +
 tests/protocol/test-qemudie-killsub.sh             |   7 +-
 tests/protocol/test-qemudie-midcommand.sh          |   7 +-
 tests/protocol/test-qemudie-synch.sh               |   7 +-
 tests/qemu/qemu-force-tcg.sh                       |  14 +-
 tests/qemu/qemu-liveness.sh                        |   1 +
 tests/qemu/qemu-snapshot-isolation.sh              |   1 +
 tests/regressions/rhbz1001875.sh                   |   7 +-
 tests/regressions/rhbz1011907-1165785.sh           |   7 +-
 tests/regressions/rhbz1044014.sh                   |  28 +--
 tests/regressions/rhbz1054761.sh                   |   7 +-
 tests/regressions/rhbz1091803.sh                   |   7 +-
 tests/regressions/rhbz1174551.sh                   |  17 +-
 tests/regressions/rhbz1175196.sh                   |   4 +-
 tests/regressions/rhbz1232192.sh                   |  35 +--
 tests/regressions/rhbz1285847.sh                   |  13 +-
 tests/regressions/rhbz1370424.sh                   |  13 +-
 tests/regressions/rhbz503169c13.sh                 |   3 +
 tests/regressions/rhbz557655.sh                    |   5 +-
 tests/regressions/rhbz563450.sh                    |  16 +-
 tests/regressions/rhbz563450b.sh                   |   8 +-
 tests/regressions/rhbz576879.sh                    |   3 +
 tests/regressions/rhbz578407.sh                    |   3 +
 tests/regressions/rhbz580246.sh                    |   4 +-
 tests/regressions/rhbz602997.sh                    |   4 +-
 tests/regressions/rhbz727178.sh                    |   4 +-
 tests/regressions/rhbz789960.sh                    |   9 +-
 tests/regressions/rhbz811649.sh                    |   4 +-
 tests/regressions/rhbz895904.sh                    |   4 +-
 tests/regressions/rhbz909624.sh                    |   8 +-
 tests/regressions/rhbz957772.sh                    |   4 +-
 tests/regressions/rhbz975797.sh                    |  36 +---
 tests/relative-paths/test-relative-paths.sh        |  11 +-
 tests/rsync/test-rsync.sh                          |  21 +-
 tests/test-functions.sh                            | 234 ++++++++++++++++++++-
 tests/tsk/test-download-blocks.sh                  |  23 +-
 tests/tsk/test-download-inode.sh                   |  24 +--
 tests/tsk/test-filesystem-walk.sh                  |  21 +-
 tests/tsk/test-find-inode.sh                       |  21 +-
 tools/test-virt-list-filesystems.sh                |   9 +-
 tools/test-virt-tar.sh                             |   9 +-
 v2v/test-v2v-bad-networks-and-bridges.sh           |  10 +-
 v2v/test-v2v-cdrom.sh                              |  34 +--
 v2v/test-v2v-conversion-of.sh                      |  21 +-
 v2v/test-v2v-copy-to-local.sh                      |  16 +-
 v2v/test-v2v-docs.sh                               |   6 +-
 v2v/test-v2v-floppy.sh                             |  33 +--
 v2v/test-v2v-i-disk.sh                             |  25 +--
 v2v/test-v2v-i-ova-formats.sh                      |  28 +--
 v2v/test-v2v-i-ova-gz.sh                           |  14 +-
 v2v/test-v2v-i-ova-subfolders.sh                   |  14 +-
 v2v/test-v2v-i-ova-tar.sh                          |  14 +-
 v2v/test-v2v-i-ova-two-disks.sh                    |  16 +-
 v2v/test-v2v-i-ova.sh                              |  33 +--
 v2v/test-v2v-in-place.sh                           |  23 +-
 v2v/test-v2v-machine-readable.sh                   |   8 +-
 v2v/test-v2v-networks-and-bridges.sh               |  25 +--
 v2v/test-v2v-no-copy.sh                            |  25 +--
 v2v/test-v2v-o-glance.sh                           |  25 +--
 v2v/test-v2v-o-libvirt.sh                          |  35 +--
 v2v/test-v2v-o-null.sh                             |  25 +--
 v2v/test-v2v-o-qemu.sh                             |  25 +--
 v2v/test-v2v-o-rhv.sh                              |  25 +--
 v2v/test-v2v-o-vdsm-options.sh                     |  25 +--
 v2v/test-v2v-oa-option.sh                          |  26 +--
 v2v/test-v2v-of-option.sh                          |  26 +--
 v2v/test-v2v-on-option.sh                          |  25 +--
 v2v/test-v2v-print-source.sh                       |  17 +-
 v2v/test-v2v-sound.sh                              |  25 +--
 v2v/test-v2v-trim.sh                               |  24 +--
 v2v/test-v2v-virtio-win-iso.sh                     |  28 +--
 v2v/test-v2v-windows-conversion.sh                 |  27 +--
 179 files changed, 1018 insertions(+), 1464 deletions(-)

diff --git a/align/test-virt-alignment-scan-docs.sh b/align/test-virt-alignment-scan-docs.sh
index ab877c6..a47cb3f 100755
--- a/align/test-virt-alignment-scan-docs.sh
+++ b/align/test-virt-alignment-scan-docs.sh
@@ -16,7 +16,9 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-$srcdir/../podcheck.pl virt-alignment-scan.pod virt-alignment-scan
+$TEST_FUNCTIONS
+skip_if_skipped
+
+$top_srcdir/podcheck.pl virt-alignment-scan.pod virt-alignment-scan
diff --git a/align/test-virt-alignment-scan-guests.sh b/align/test-virt-alignment-scan-guests.sh
index 3481752..d149274 100755
--- a/align/test-virt-alignment-scan-guests.sh
+++ b/align/test-virt-alignment-scan-guests.sh
@@ -16,15 +16,10 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
+$TEST_FUNCTIONS
+skip_if_skipped
 
-if [ -n "$SKIP_TEST_VIRT_ALIGNMENT_SCAN_GUESTS_SH" ]; then
-    echo "$0: skipping test because SKIP_TEST_VIRT_ALIGNMENT_SCAN_GUESTS_SH is set."
-    exit 77
-fi
-
-guestsdir="$(cd ../test-data/phony-guests && pwd)"
-libvirt_uri="test://$guestsdir/guests-all-good.xml"
+libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests-all-good.xml"
 
 $VG virt-alignment-scan -c "$libvirt_uri"
 r=$?
diff --git a/align/test-virt-alignment-scan.sh b/align/test-virt-alignment-scan.sh
index ab44c26..59688f6 100755
--- a/align/test-virt-alignment-scan.sh
+++ b/align/test-virt-alignment-scan.sh
@@ -16,7 +16,8 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
+$TEST_FUNCTIONS
+skip_if_skipped
 
 $VG virt-alignment-scan --format=raw -a ../test-data/phony-guests/fedora.img
 r=$?
diff --git a/bash/test-complete-in-script.sh b/bash/test-complete-in-script.sh
index 6b33626..7fff0bc 100755
--- a/bash/test-complete-in-script.sh
+++ b/bash/test-complete-in-script.sh
@@ -19,13 +19,8 @@
 # Test that the correct 'complete' command is included in the script.
 # Mainly prevents symlinking errors and some omissions.
 
-unset CDPATH
-export LANG=C
-
-if [ -n "$SKIP_TEST_COMPLETE_IN_SCRIPT_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
 
 if [ -z "$commands" ]; then
     echo "$0: \$commands is not defined.  Use 'make check' to run this test."
diff --git a/builder/test-console.sh b/builder/test-console.sh
index 209fd21..64e5b17 100755
--- a/builder/test-console.sh
+++ b/builder/test-console.sh
@@ -24,19 +24,11 @@
 # The script currently assumes a Linux guest.  We should test Windows,
 # FreeBSD in future (XXX).
 
-export LANG=C
 set -e
 
-if [ -z "$SLOW" ]; then
-    echo "$script: use 'make check-slow' to run this test"
-    exit 77
-fi
-
-skipenv="$(echo SKIP_$script | tr a-z.- A-Z__)"
-if [ -n "${!skipenv}" ]; then
-    echo "$script: test skipped because environment variable is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+slow_test
+skip_if_skipped "$script"
 
 guestname="$1"
 if [ -z "$guestname" ]; then
@@ -46,23 +38,14 @@ fi
 
 # If the guest doesn't exist in virt-builder, skip.  This is because
 # we test some RHEL guests which most users won't have access to.
-if ! virt-builder -l "$guestname" >/dev/null 2>&1; then
-    echo "$script: test skipped because \"$guestname\" not known to virt-builder."
-    exit 77
-fi
+skip_unless_virt_builder_guest "$guestname"
 
 # We can only run the tests on x86_64.
-if [ "$(uname -m)" != "x86_64" ]; then
-    echo "$script: test skipped because !x86_64."
-    exit 77
-fi
+skip_unless_arch x86_64
 
 # Check qemu is installed.
 qemu=qemu-system-x86_64
-if ! $qemu -help >/dev/null 2>&1; then
-    echo "$script: test skipped because $qemu not found."
-    exit 77
-fi
+skip_unless $qemu -help
 
 # Some guests need special virt-builder parameters.
 # See virt-builder --notes "$guestname"
diff --git a/builder/test-virt-builder-docs.sh b/builder/test-virt-builder-docs.sh
index 83e2f49..884135d 100755
--- a/builder/test-virt-builder-docs.sh
+++ b/builder/test-virt-builder-docs.sh
@@ -16,10 +16,12 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-$srcdir/../podcheck.pl virt-builder.pod virt-builder \
-  --insert $srcdir/../customize/customize-synopsis.pod:__CUSTOMIZE_SYNOPSIS__ \
-  --insert $srcdir/../customize/customize-options.pod:__CUSTOMIZE_OPTIONS__ \
+$TEST_FUNCTIONS
+skip_if_skipped
+
+$top_srcdir/podcheck.pl virt-builder.pod virt-builder \
+  --insert $top_srcdir/customize/customize-synopsis.pod:__CUSTOMIZE_SYNOPSIS__ \
+  --insert $top_srcdir/customize/customize-options.pod:__CUSTOMIZE_OPTIONS__ \
   --ignore=--check-signatures,--no-check-signatures
diff --git a/builder/test-virt-builder-list-simplestreams.sh b/builder/test-virt-builder-list-simplestreams.sh
index 24cf44c..29fbfac 100755
--- a/builder/test-virt-builder-list-simplestreams.sh
+++ b/builder/test-virt-builder-list-simplestreams.sh
@@ -16,10 +16,10 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-abs_builddir=$(pwd)
+$TEST_FUNCTIONS
+skip_if_skipped
 
 export XDG_CONFIG_HOME=
 export XDG_CONFIG_DIRS="$abs_builddir/test-simplestreams"
diff --git a/builder/test-virt-builder-list.sh b/builder/test-virt-builder-list.sh
index 2b6dfad..66910fc 100755
--- a/builder/test-virt-builder-list.sh
+++ b/builder/test-virt-builder-list.sh
@@ -18,10 +18,10 @@
 
 # Test the virt-builder --list [--long] options.
 
-export LANG=C
 set -e
 
-abs_builddir=$(pwd)
+$TEST_FUNCTIONS
+skip_if_skipped
 
 export XDG_CONFIG_HOME=
 export XDG_CONFIG_DIRS="$abs_builddir/test-config"
diff --git a/builder/test-virt-builder-planner.sh b/builder/test-virt-builder-planner.sh
index b293e87..108b70e 100755
--- a/builder/test-virt-builder-planner.sh
+++ b/builder/test-virt-builder-planner.sh
@@ -16,34 +16,21 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-abs_builddir=$(pwd)
+$TEST_FUNCTIONS
+slow_test
+skip_if_skipped
+skip_if_backend uml
 
 export XDG_CONFIG_HOME=
 export XDG_CONFIG_DIRS="$abs_builddir/test-config"
 
-if [ -z "$SLOW" ]; then
-    echo "$0: use 'make check-slow' to run this test"
-    exit 77
-fi
-
-if [ -n "$SKIP_TEST_VIRT_BUILDER_PLANNER_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
-
 if [ ! -f fedora.xz -o ! -f fedora.qcow2 -o ! -f fedora.qcow2.xz ]; then
     echo "$0: test skipped because there is no fedora.xz, fedora.qcow2 or fedora.qcow2.xz in the build directory"
     exit 77
 fi
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because backend is UML"
-    exit 77
-fi
-
 rm -f planner-output
 
 for input in phony-fedora phony-fedora-qcow2 phony-fedora-qcow2-uncompressed phony-fedora-no-format; do
diff --git a/builder/test-virt-builder.sh b/builder/test-virt-builder.sh
index 6e254e5..1867387 100755
--- a/builder/test-virt-builder.sh
+++ b/builder/test-virt-builder.sh
@@ -16,19 +16,14 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-abs_builddir=$(pwd)
+$TEST_FUNCTIONS
+skip_if_skipped
 
 export XDG_CONFIG_HOME=
 export XDG_CONFIG_DIRS="$abs_builddir/test-config"
 
-if [ -n "$SKIP_TEST_VIRT_BUILDER_SH" ]; then
-    echo "$0: skipping test because environment variable is set."
-    exit 77
-fi
-
 if [ ! -f fedora.xz ]; then
     echo "$0: test skipped because there is no fedora.xz in the build directory"
     exit 77
diff --git a/cat/test-docs.sh b/cat/test-docs.sh
index d8ac358..30cc1ee 100755
--- a/cat/test-docs.sh
+++ b/cat/test-docs.sh
@@ -16,12 +16,14 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-$srcdir/../podcheck.pl virt-cat.pod virt-cat
-$srcdir/../podcheck.pl virt-filesystems.pod virt-filesystems
-$srcdir/../podcheck.pl virt-log.pod virt-log
-$srcdir/../podcheck.pl virt-ls.pod virt-ls \
-                       --ignore=--checksums,--extra-stat,--time,--uid
-$srcdir/../podcheck.pl virt-tail.pod virt-tail
+$TEST_FUNCTIONS
+skip_if_skipped
+
+$top_srcdir/podcheck.pl virt-cat.pod virt-cat
+$top_srcdir/podcheck.pl virt-filesystems.pod virt-filesystems
+$top_srcdir/podcheck.pl virt-log.pod virt-log
+$top_srcdir/podcheck.pl virt-ls.pod virt-ls \
+                        --ignore=--checksums,--extra-stat,--time,--uid
+$top_srcdir/podcheck.pl virt-tail.pod virt-tail
diff --git a/cat/test-virt-cat.sh b/cat/test-virt-cat.sh
index 4d9f252..55089cc 100755
--- a/cat/test-virt-cat.sh
+++ b/cat/test-virt-cat.sh
@@ -16,9 +16,11 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 # Read out the test files from the image using virt-cat.
 if [ "$($VG virt-cat --format=raw -a ../test-data/phony-guests/fedora.img /etc/test1)" != "abcdefg" ]; then
     echo "$0: error: mismatch in file test1"
diff --git a/cat/test-virt-filesystems.sh b/cat/test-virt-filesystems.sh
index c375b35..07c6354 100755
--- a/cat/test-virt-filesystems.sh
+++ b/cat/test-virt-filesystems.sh
@@ -16,9 +16,11 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 output="$($VG virt-filesystems --format=raw -a ../test-data/phony-guests/fedora.img | sort)"
 expected="/dev/VG/LV1
 /dev/VG/LV2
diff --git a/cat/test-virt-log.sh b/cat/test-virt-log.sh
index 979bd96..4436505 100755
--- a/cat/test-virt-log.sh
+++ b/cat/test-virt-log.sh
@@ -16,9 +16,11 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 can_handle ()
 {
     fn=$(basename $1)
diff --git a/cat/test-virt-ls.sh b/cat/test-virt-ls.sh
index 4b7d927..02e1f02 100755
--- a/cat/test-virt-ls.sh
+++ b/cat/test-virt-ls.sh
@@ -16,9 +16,11 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 # Read out the test directory using virt-ls.
 if [ "$($VG virt-ls --format=raw -a ../test-data/phony-guests/fedora.img /bin)" != "ls
 test1
diff --git a/cat/test-virt-tail.sh b/cat/test-virt-tail.sh
index 518bbf7..47a5edc 100755
--- a/cat/test-virt-tail.sh
+++ b/cat/test-virt-tail.sh
@@ -21,17 +21,16 @@
 # in the guestfish instance we append to the file, and we check that
 # the addenda are displayed by virt-tail.
 
-export LANG=C
 set -e
 set -x
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 # Libvirt screws with the SELinux labels, preventing guestfish from
 # continuing to write to the original disk.  Therefore only run this
 # test when using direct access.
-if [ "$(guestfish get-backend)" != "direct" ]; then
-    echo "$0: test skipped because default backend is not 'direct'"
-    exit 77
-fi
+skip_unless_backend direct
 
 out=test-virt-tail.out
 disk=test-virt-tail.disk
diff --git a/customize/test-firstboot.sh b/customize/test-firstboot.sh
index 4a41c7b..b5bd0d1 100755
--- a/customize/test-firstboot.sh
+++ b/customize/test-firstboot.sh
@@ -21,18 +21,11 @@
 # NB. 'test-firstboot.sh' runs the tests, but the various tests are
 # run via the 'test-firstboot-GUESTNAME.sh' wrappers.
 
-export LANG=C
 set -e
 
-if [ -z "$SLOW" ]; then
-    echo "$script: use 'make check-slow' to run this test"
-    exit 77
-fi
-
-if [ -n "$SKIP_TEST_FIRSTBOOT_SH" ]; then
-    echo "$script: test skipped because environment variable is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+slow_test
+skip_if_skipped "$script"
 
 guestname="$1"
 if [ -z "$guestname" ]; then
@@ -45,23 +38,14 @@ rm -f "$disk"
 
 # If the guest doesn't exist in virt-builder, skip.  This is because
 # we test some RHEL guests which most users won't have access to.
-if ! virt-builder -l "$guestname" >/dev/null 2>&1; then
-    echo "$script: test skipped because \"$guestname\" not known to virt-builder."
-    exit 77
-fi
+skip_unless_virt_builder_guest "$guestname"
 
 # We can only run the tests on x86_64.
-if [ "$(uname -m)" != "x86_64" ]; then
-    echo "$script: test skipped because !x86_64."
-    exit 77
-fi
+skip_unless_arch x86_64
 
 # Check qemu is installed.
 qemu=qemu-system-x86_64
-if ! $qemu -help >/dev/null 2>&1; then
-    echo "$script: test skipped because $qemu not found."
-    exit 77
-fi
+skip_unless $qemu -help
 
 # Some guests need special virt-builder parameters.
 # See virt-builder --notes "$guestname"
diff --git a/customize/test-settings.sh b/customize/test-settings.sh
index e56561c..a86c9da 100755
--- a/customize/test-settings.sh
+++ b/customize/test-settings.sh
@@ -21,19 +21,12 @@
 # NB. 'test-settings.sh' runs the tests, but the various tests are
 # run via the 'test-settings-GUESTNAME.sh' wrappers.
 
-export LANG=C
 set -e
 set -x
 
-if [ -z "$SLOW" ]; then
-    echo "$script: use 'make check-slow' to run this test"
-    exit 77
-fi
-
-if [ -n "$SKIP_TEST_SETTINGS_SH" ]; then
-    echo "$script: test skipped because environment variable is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+slow_test
+skip_if_skipped "$script"
 
 guestname="$1"
 if [ -z "$guestname" ]; then
@@ -46,23 +39,14 @@ rm -f "$disk" "$disk.firstboot.sh" "$disk.firstboot.out"
 
 # If the guest doesn't exist in virt-builder, skip.  This is because
 # we test some RHEL guests which most users won't have access to.
-if ! virt-builder -l "$guestname" >/dev/null 2>&1; then
-    echo "$script: test skipped because \"$guestname\" not known to virt-builder."
-    exit 77
-fi
+skip_unless_virt_builder_guest "$guestname"
 
 # We can only run the tests on x86_64.
-if [ "$(uname -m)" != "x86_64" ]; then
-    echo "$script: test skipped because !x86_64."
-    exit 77
-fi
+skip_unless_arch x86_64
 
 # Check qemu is installed.
 qemu=qemu-system-x86_64
-if ! $qemu -help >/dev/null 2>&1; then
-    echo "$script: test skipped because $qemu not found."
-    exit 77
-fi
+skip_unless $qemu -help
 
 # Some guests need special virt-builder parameters.
 # See virt-builder --notes "$guestname"
diff --git a/customize/test-virt-customize-docs.sh b/customize/test-virt-customize-docs.sh
index c5e2ebf..ddaedea 100755
--- a/customize/test-virt-customize-docs.sh
+++ b/customize/test-virt-customize-docs.sh
@@ -16,10 +16,11 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-$srcdir/../podcheck.pl virt-customize.pod virt-customize \
-  --insert $srcdir/../customize/customize-synopsis.pod:__CUSTOMIZE_SYNOPSIS__ \
-  --insert $srcdir/../customize/customize-options.pod:__CUSTOMIZE_OPTIONS__ \
+$TEST_FUNCTIONS
+
+$top_srcdir/podcheck.pl virt-customize.pod virt-customize \
+  --insert $top_srcdir/customize/customize-synopsis.pod:__CUSTOMIZE_SYNOPSIS__ \
+  --insert $top_srcdir/customize/customize-options.pod:__CUSTOMIZE_OPTIONS__ \
   --ignore=--dryrun
diff --git a/customize/test-virt-customize.sh b/customize/test-virt-customize.sh
index 6c74e1d..0c5231b 100755
--- a/customize/test-virt-customize.sh
+++ b/customize/test-virt-customize.sh
@@ -16,21 +16,14 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 set -x
 
-if [ -n "$SKIP_TEST_VIRT_CUSTOMIZE_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
-
-f=../test-data/phony-guests/fedora.img
-if [ ! -s $f ]; then
-    echo "$0: test skipped because there is no fedora.img"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_phony_guest fedora.img
 
+f=$top_builddir/test-data/phony-guests/fedora.img
 fq=test-virt-customize-img.qcow
 out=test-virt-customize.out
 rm -f $fq $out
diff --git a/df/test-virt-df-docs.sh b/df/test-virt-df-docs.sh
index f4f582c..94061d1 100755
--- a/df/test-virt-df-docs.sh
+++ b/df/test-virt-df-docs.sh
@@ -16,7 +16,8 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-$srcdir/../podcheck.pl virt-df.pod virt-df
+$TEST_FUNCTIONS
+
+$top_srcdir/podcheck.pl virt-df.pod virt-df
diff --git a/df/test-virt-df-guests.sh b/df/test-virt-df-guests.sh
index 68c381e..5edbe17 100755
--- a/df/test-virt-df-guests.sh
+++ b/df/test-virt-df-guests.sh
@@ -18,15 +18,11 @@
 
 # Run virt-df on the test guests.
 
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_VIRT_DF_GUESTS_SH" ]; then
-    echo "$0: skipping test because SKIP_TEST_DF_GUESTS_SH is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
 
-guestsdir="$(cd ../test-data/phony-guests && pwd)"
-libvirt_uri="test://$guestsdir/guests.xml"
+libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml"
 
 $VG virt-df -c "$libvirt_uri"
diff --git a/df/test-virt-df.sh b/df/test-virt-df.sh
index eaa4ff3..2dc604f 100755
--- a/df/test-virt-df.sh
+++ b/df/test-virt-df.sh
@@ -16,9 +16,10 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
+$TEST_FUNCTIONS
+
 # Run virt-df.
 output=$($VG virt-df --format=raw -a ../test-data/phony-guests/fedora.img)
 
diff --git a/dib/test-virt-dib-docs.sh b/dib/test-virt-dib-docs.sh
index 11d7e1e..3363c9e 100755
--- a/dib/test-virt-dib-docs.sh
+++ b/dib/test-virt-dib-docs.sh
@@ -16,7 +16,8 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-$srcdir/../podcheck.pl virt-dib.pod virt-dib
+$TEST_FUNCTIONS
+
+$top_srcdir/podcheck.pl virt-dib.pod virt-dib
diff --git a/diff/test-virt-diff-docs.sh b/diff/test-virt-diff-docs.sh
index f1262d6..cf6ce72 100755
--- a/diff/test-virt-diff-docs.sh
+++ b/diff/test-virt-diff-docs.sh
@@ -16,8 +16,9 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-$srcdir/../podcheck.pl virt-diff.pod virt-diff \
+$TEST_FUNCTIONS
+
+$top_srcdir/podcheck.pl virt-diff.pod virt-diff \
   --ignore=--checksums,--dir-link,--dir-nlink,--dir-nlinks,--dir-time,--extra-stat,--time,--uid,--xattr
diff --git a/diff/test-virt-diff.sh b/diff/test-virt-diff.sh
index 5a63515..4984999 100755
--- a/diff/test-virt-diff.sh
+++ b/diff/test-virt-diff.sh
@@ -16,18 +16,12 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-if [ ! -f ../test-data/phony-guests/fedora.img ]; then
-    echo "$0: test skipped because there is no phony fedora test image"
-    exit 77
-fi
-
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because backend is UML"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
+skip_unless_phony_guest fedora.img
 
 rm -f fedora.qcow2
 
diff --git a/docs/guestfs-hacking.pod b/docs/guestfs-hacking.pod
index 43b69e6..8f320cc 100644
--- a/docs/guestfs-hacking.pod
+++ b/docs/guestfs-hacking.pod
@@ -643,7 +643,9 @@ normal test.
 =item *
 
 Modify the test so it checks if the C<SLOW=1> environment variable is
-set, and if I<not> set it skips (ie. returns with exit code 77).
+set, and if I<not> set it skips (ie. returns with exit code 77).  If
+using C<$TEST_FUNCTIONS>, you can call the function C<slow_test> for
+this.
 
 =item *
 
diff --git a/edit/test-virt-edit-docs.sh b/edit/test-virt-edit-docs.sh
index 85794ce..d824db9 100755
--- a/edit/test-virt-edit-docs.sh
+++ b/edit/test-virt-edit-docs.sh
@@ -16,7 +16,8 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-$srcdir/../podcheck.pl virt-edit.pod virt-edit
+$TEST_FUNCTIONS
+
+$top_srcdir/podcheck.pl virt-edit.pod virt-edit
diff --git a/edit/test-virt-edit.sh b/edit/test-virt-edit.sh
index bcf6847..03b03ba 100755
--- a/edit/test-virt-edit.sh
+++ b/edit/test-virt-edit.sh
@@ -16,13 +16,12 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: skipping test because uml backend does not support qcow2"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+# UML backend does not support qcow2.
+skip_if_backend uml
 
 rm -f test.qcow2
 
diff --git a/fish/test-a.sh b/fish/test-a.sh
index 0fcc7d1..e045704 100755
--- a/fish/test-a.sh
+++ b/fish/test-a.sh
@@ -20,6 +20,9 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 rm -f test-a.out
 rm -f test-a.img
 
diff --git a/fish/test-add-domain.sh b/fish/test-add-domain.sh
index 608d2de..8de1126 100755
--- a/fish/test-add-domain.sh
+++ b/fish/test-add-domain.sh
@@ -20,11 +20,12 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 rm -f test-add-domain-{1,2,3,4}.img
 rm -f test-add-domain.xml test-add-domain.out
 
-cwd="$(pwd)"
-
 $VG guestfish sparse test-add-domain-1.img 1M
 $VG guestfish sparse test-add-domain-2.img 1M
 $VG guestfish disk-create test-add-domain-3.img qcow2 1M
@@ -42,22 +43,22 @@ cat > test-add-domain.xml <<EOF
     <memory>524288</memory>
     <devices>
       <disk type="file">
-        <source file="$cwd/test-add-domain-1.img"/>
+        <source file="$abs_builddir/test-add-domain-1.img"/>
         <target dev="hda"/>
       </disk>
       <disk type="file">
         <driver name="qemu" type="raw"/>
-        <source file="$cwd/test-add-domain-2.img"/>
+        <source file="$abs_builddir/test-add-domain-2.img"/>
         <target dev="hdb"/>
       </disk>
       <disk type="file">
         <driver name="qemu" type="qcow2"/>
-        <source file="$cwd/test-add-domain-3.img"/>
+        <source file="$abs_builddir/test-add-domain-3.img"/>
         <target dev="hdc"/>
       </disk>
       <disk type="file">
         <driver name="qemu" type="raw"/>
-        <source file="$cwd/test-add-domain-4.img"/>
+        <source file="$abs_builddir/test-add-domain-4.img"/>
         <target dev="hdd"/>
         <readonly/>
       </disk>
@@ -67,7 +68,7 @@ cat > test-add-domain.xml <<EOF
 EOF
 
 $VG guestfish >test-add-domain.out <<EOF
-  domain guest libvirturi:test://$cwd/test-add-domain.xml readonly:true
+  domain guest libvirturi:test://$abs_builddir/test-add-domain.xml readonly:true
   debug-drives
 EOF
 grep -sq "test-add-domain-1.img readonly" test-add-domain.out
@@ -77,7 +78,7 @@ grep -sq "test-add-domain-3.img readonly format=qcow2" test-add-domain.out
 
 # Test readonlydisk = "ignore".
 $VG guestfish >test-add-domain.out <<EOF
-  -domain guest libvirturi:test://$cwd/test-add-domain.xml readonly:true readonlydisk:ignore
+  -domain guest libvirturi:test://$abs_builddir/test-add-domain.xml readonly:true readonlydisk:ignore
   debug-drives
 EOF
 grep -sq "test-add-domain-1.img" test-add-domain.out
@@ -89,7 +90,7 @@ grep -sq "test-add-domain-3.img" test-add-domain.out
 rm test-add-domain-3.img
 
 $VG guestfish >test-add-domain.out <<EOF
-  -domain guest libvirturi:test://$cwd/test-add-domain.xml readonly:true
+  -domain guest libvirturi:test://$abs_builddir/test-add-domain.xml readonly:true
   debug-drives
 EOF
 ! grep -sq "test-add-domain-1.img" test-add-domain.out
diff --git a/fish/test-add-uri.sh b/fish/test-add-uri.sh
index 07b68c4..756df99 100755
--- a/fish/test-add-uri.sh
+++ b/fish/test-add-uri.sh
@@ -21,6 +21,9 @@
 set -e
 set -x
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 rm -f test-add-uri.out
 rm -f test-add-uri.img
 
@@ -34,7 +37,7 @@ function fail ()
 }
 
 # file:// URI should be handled exactly like a regular file.
-$VG guestfish -x -a file://$(pwd)/test-add-uri.img </dev/null >test-add-uri.out 2>&1
+$VG guestfish -x -a file://$abs_builddir/test-add-uri.img </dev/null >test-add-uri.out 2>&1
 grep -sq 'add_drive ".*/test-add-uri.img"' test-add-uri.out || fail
 
 # curl
diff --git a/fish/test-alloc.sh b/fish/test-alloc.sh
index 98f8f4e..168e75d 100755
--- a/fish/test-alloc.sh
+++ b/fish/test-alloc.sh
@@ -20,6 +20,9 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 rm -f test-alloc.img
 
 $VG guestfish alloc test-alloc.img 200000
diff --git a/fish/test-copy.sh b/fish/test-copy.sh
index f375beb..a073998 100755
--- a/fish/test-copy.sh
+++ b/fish/test-copy.sh
@@ -18,6 +18,11 @@
 
 # Test guestfish copy-in and copy-out commands.
 
+set -e
+
+$TEST_FUNCTIONS
+skip_if_skipped
+
 # This test fails on some versions of mock which lack /dev/fd
 # directory.  Skip this test in that case.
 
@@ -26,8 +31,6 @@ test -d /dev/fd || {
     exit 77
 }
 
-set -e
-
 rm -f test-copy.img
 rm -rf test-copy-original test-copy-copy
 
diff --git a/fish/test-d.sh b/fish/test-d.sh
index 4c41ce0..6ef8ff0 100755
--- a/fish/test-d.sh
+++ b/fish/test-d.sh
@@ -20,11 +20,12 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 rm -f test-d-{1,2,3,4}.img
 rm -f test-d.xml test-d.out
 
-cwd="$(pwd)"
-
 $VG guestfish sparse test-d-1.img 1M
 $VG guestfish sparse test-d-2.img 1M
 $VG guestfish disk-create test-d-3.img qcow2 1M
@@ -42,22 +43,22 @@ cat > test-d.xml <<EOF
     <memory>524288</memory>
     <devices>
       <disk type="file">
-        <source file="$cwd/test-d-1.img"/>
+        <source file="$abs_builddir/test-d-1.img"/>
         <target dev="hda"/>
       </disk>
       <disk type="file">
         <driver name="qemu" type="raw"/>
-        <source file="$cwd/test-d-2.img"/>
+        <source file="$abs_builddir/test-d-2.img"/>
         <target dev="hdb"/>
       </disk>
       <disk type="file">
         <driver name="qemu" type="qcow2"/>
-        <source file="$cwd/test-d-3.img"/>
+        <source file="$abs_builddir/test-d-3.img"/>
         <target dev="hdc"/>
       </disk>
       <disk type="file">
         <driver name="qemu" type="raw"/>
-        <source file="$cwd/test-d-4.img"/>
+        <source file="$abs_builddir/test-d-4.img"/>
         <target dev="hdd"/>
         <readonly/>
       </disk>
@@ -66,7 +67,7 @@ cat > test-d.xml <<EOF
 </node>
 EOF
 
-$VG guestfish -c "test://$cwd/test-d.xml" --ro -d guest \
+$VG guestfish -c "test://$abs_builddir/test-d.xml" --ro -d guest \
   debug-drives </dev/null >test-d.out
 grep -sq "test-d-1.img readonly" test-d.out
 ! grep -sq "test-d-1.img.*format" test-d.out
diff --git a/fish/test-docs.sh b/fish/test-docs.sh
index 07ba9f8..6630da4 100755
--- a/fish/test-docs.sh
+++ b/fish/test-docs.sh
@@ -16,10 +16,12 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-$srcdir/../podcheck.pl guestfish.pod guestfish \
+$TEST_FUNCTIONS
+skip_if_skipped
+
+$top_srcdir/podcheck.pl guestfish.pod guestfish \
     --insert $srcdir/guestfish-actions.pod:__ACTIONS__ \
     --insert $srcdir/guestfish-commands.pod:__FISH_COMMANDS__ \
     --insert $srcdir/guestfish-prepopts.pod:__PREPOPTS__ \
diff --git a/fish/test-edit.sh b/fish/test-edit.sh
index 9242617..6bc16c5 100755
--- a/fish/test-edit.sh
+++ b/fish/test-edit.sh
@@ -18,6 +18,11 @@
 
 # Test guestfish edit command.
 
+set -e
+
+$TEST_FUNCTIONS
+skip_if_skipped
+
 # This test fails on some versions of mock which lack /dev/fd
 # directory.  Skip this test in that case.
 
@@ -26,8 +31,6 @@ test -d /dev/fd || {
     exit 77
 }
 
-set -e
-
 rm -f test-edit.img
 
 # The command will be 'echo ... >>/tmp/tmpfile'
diff --git a/fish/test-escapes.sh b/fish/test-escapes.sh
index 18c6e03..f75e828 100755
--- a/fish/test-escapes.sh
+++ b/fish/test-escapes.sh
@@ -20,6 +20,9 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 rm -f test.output test.error test.error.old
 
 $VG guestfish <<'EOF' 2>test.error | od -b > test.output
diff --git a/fish/test-events.sh b/fish/test-events.sh
index 7d4cd82..1faec1b 100755
--- a/fish/test-events.sh
+++ b/fish/test-events.sh
@@ -20,6 +20,9 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 rm -f test-events.out
 
 $VG guestfish -a /dev/null <<'EOF' | grep -v get_verbose | grep -v get_trace | grep -v 'library .*0x' | grep -v 'library command' | grep -v 'get_path' > test-events.out
diff --git a/fish/test-file-attrs.sh b/fish/test-file-attrs.sh
index 7f34348..f726297 100755
--- a/fish/test-file-attrs.sh
+++ b/fish/test-file-attrs.sh
@@ -19,7 +19,9 @@
 # Test guestfish file attributes commands (chmod, copy-attributes, etc).
 
 set -e
-export LANG=C
+
+$TEST_FUNCTIONS
+skip_if_skipped
 
 rm -f test-file-attrs.out
 
diff --git a/fish/test-find0.sh b/fish/test-find0.sh
index f327761..700e947 100755
--- a/fish/test-find0.sh
+++ b/fish/test-find0.sh
@@ -20,10 +20,14 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_test_iso
+
 rm -f test-find0.out
 
-$VG guestfish <<'EOF'
-add-ro ../test-data/test.iso
+$VG guestfish <<EOF
+add-ro $top_builddir/test-data/test.iso
 run
 mount-ro /dev/sda /
 find0 / test-find0.out
diff --git a/fish/test-glob.sh b/fish/test-glob.sh
index c520319..cf00d95 100755
--- a/fish/test-glob.sh
+++ b/fish/test-glob.sh
@@ -20,6 +20,9 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 rm -f test-glob.img test-glob.out
 
 $VG guestfish -N test-glob.img=disk:1G > test-glob.out <<EOF
diff --git a/fish/test-inspect.sh b/fish/test-inspect.sh
index 1a47dd2..3133eeb 100755
--- a/fish/test-inspect.sh
+++ b/fish/test-inspect.sh
@@ -18,4 +18,11 @@
 
 set -e
 
-$VG guestfish --ro --format=raw -a ../test-data/phony-guests/fedora.img -i exit
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_phony_guest fedora.img
+
+$VG guestfish \
+    --ro --format=raw -a $top_builddir/test-data/phony-guests/fedora.img \
+    -i \
+    exit
diff --git a/fish/test-invalid-params.sh b/fish/test-invalid-params.sh
index 7d02c65..af548c1 100755
--- a/fish/test-invalid-params.sh
+++ b/fish/test-invalid-params.sh
@@ -21,6 +21,9 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 # Memory size
 output=$(
 $VG guestfish <<EOF
diff --git a/fish/test-mount-local.sh b/fish/test-mount-local.sh
index 0ab0ce1..3ec87dc 100755
--- a/fish/test-mount-local.sh
+++ b/fish/test-mount-local.sh
@@ -18,18 +18,9 @@
 
 # Test guestfish mount-local / mount-local-run commands.
 
-if [ -n "$SKIP_TEST_MOUNT_LOCAL_SH" ]; then
-    echo "$0: skipping test because SKIP_TEST_MOUNT_LOCAL_SH is set."
-    exit 77
-fi
-
-# Skip if no FUSE.
-
-test -w /dev/fuse || {
-    echo "$0: Skipping this test"
-    echo "  because /dev/fuse is missing or not writable by the current user."
-    exit 77
-}
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_fuse
 
 set -e
 
diff --git a/fish/test-read-file.sh b/fish/test-read-file.sh
index b83faa9..f2357a1 100755
--- a/fish/test-read-file.sh
+++ b/fish/test-read-file.sh
@@ -20,15 +20,19 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_test_iso
+
 rm -f test-read-file.out
 
-$VG guestfish <<'EOF' > test-read-file.out
-add-ro ../test-data/test.iso
+$VG guestfish <<EOF > test-read-file.out
+add-ro $top_builddir/test-data/test.iso
 run
 mount-ro /dev/sda /
 read-file /helloworld.tar
 EOF
 
-cmp $srcdir/../test-data/files/helloworld.tar test-read-file.out
+cmp $top_srcdir/test-data/files/helloworld.tar test-read-file.out
 
 rm -f test-read-file.out
diff --git a/fish/test-remote-events.sh b/fish/test-remote-events.sh
index c05f072..5e78552 100755
--- a/fish/test-remote-events.sh
+++ b/fish/test-remote-events.sh
@@ -20,6 +20,9 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 eval "$(guestfish --listen)"
 
 $VG guestfish --remote event close_event close "echo closed"
diff --git a/fish/test-remote.sh b/fish/test-remote.sh
index 28df682..eb169c6 100755
--- a/fish/test-remote.sh
+++ b/fish/test-remote.sh
@@ -20,6 +20,9 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 rm -f test-remote.img
 
 eval `guestfish --listen`
diff --git a/fish/test-reopen.sh b/fish/test-reopen.sh
index d8966d4..35070b4 100755
--- a/fish/test-reopen.sh
+++ b/fish/test-reopen.sh
@@ -21,6 +21,9 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 rm -f test-reopen.img
 
 $VG guestfish <<'EOF'
diff --git a/fish/test-run.sh b/fish/test-run.sh
index 237ecf7..95d861e 100755
--- a/fish/test-run.sh
+++ b/fish/test-run.sh
@@ -18,4 +18,10 @@
 
 set -e
 
-$VG guestfish --ro --format=raw -a ../test-data/phony-guests/fedora.img run
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_phony_guest fedora.img
+
+$VG guestfish \
+    --ro --format=raw -a $top_builddir/test-data/phony-guests/fedora.img \
+    run
diff --git a/fish/test-stringlist.sh b/fish/test-stringlist.sh
index ab23cb9..3d8ebb8 100755
--- a/fish/test-stringlist.sh
+++ b/fish/test-stringlist.sh
@@ -20,6 +20,9 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 rm -f test-stringlist.img
 
 eval `guestfish --listen`
diff --git a/fish/test-tilde.sh b/fish/test-tilde.sh
index ca4af73..7752638 100755
--- a/fish/test-tilde.sh
+++ b/fish/test-tilde.sh
@@ -23,6 +23,9 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 # Don't rely on $HOME being set when this script is called.
 HOME=$(pwd)
 export HOME
diff --git a/fish/test-upload-to-dir.sh b/fish/test-upload-to-dir.sh
index a62df64..a946611 100755
--- a/fish/test-upload-to-dir.sh
+++ b/fish/test-upload-to-dir.sh
@@ -22,9 +22,16 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_test_iso
+
 rm -f test-upload-to-dir.img test-upload-to-dir.out
 
-if $VG guestfish -N test-upload-to-dir.img=fs -m /dev/sda1 upload ../test-data/test.iso / 2>test-upload-to-dir.out
+if $VG guestfish \
+       -N test-upload-to-dir.img=fs \
+       -m /dev/sda1 \
+       upload $top_builddir/test-data/test.iso / 2>test-upload-to-dir.out
 then
   echo "$0: expecting guestfish to return an error"
   exit 1
diff --git a/format/test-virt-format-docs.sh b/format/test-virt-format-docs.sh
index f00456a..27275f0 100755
--- a/format/test-virt-format-docs.sh
+++ b/format/test-virt-format-docs.sh
@@ -16,7 +16,9 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-$srcdir/../podcheck.pl virt-format.pod virt-format
+$TEST_FUNCTIONS
+skip_if_skipped
+
+$top_srcdir/podcheck.pl virt-format.pod virt-format
diff --git a/format/test-virt-format.sh b/format/test-virt-format.sh
index bca0c05..b89ae08 100755
--- a/format/test-virt-format.sh
+++ b/format/test-virt-format.sh
@@ -20,10 +20,8 @@
 
 set -e
 
-if [ -n "$SKIP_TEST_VIRT_FORMAT_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
 
 rm -f test-virt-format.img
 
diff --git a/fuse/test-docs.sh b/fuse/test-docs.sh
index 93bca2d..ba2c9c5 100755
--- a/fuse/test-docs.sh
+++ b/fuse/test-docs.sh
@@ -16,11 +16,13 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-$srcdir/../podcheck.pl guestmount.pod guestmount
+$TEST_FUNCTIONS
+skip_if_skipped
+
+$top_srcdir/podcheck.pl guestmount.pod guestmount
 
 # guestunmount doesn't implement bash completion, so we cannot
 # test it at the moment. XXX
-#$srcdir/../podcheck.pl guestunmount.pod guestunmount
+#$top_srcdir/podcheck.pl guestunmount.pod guestunmount
diff --git a/fuse/test-fuse-umount-race.sh b/fuse/test-fuse-umount-race.sh
index 5d582c4..cfb5fe3 100755
--- a/fuse/test-fuse-umount-race.sh
+++ b/fuse/test-fuse-umount-race.sh
@@ -19,34 +19,15 @@
 # https://bugzilla.redhat.com/show_bug.cgi?id=838592
 # This tests that the --pid-file option can be used to fix the race.
 
-unset CDPATH
 set -e
-#set -v
 
-if [ -n "$SKIP_TEST_FUSE_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
-
-if [ -n "$SKIP_TEST_FUSE_UMOUNT_RACE_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
-
-if [ ! -w /dev/fuse ]; then
-    echo "$0: test skipped because there is no /dev/fuse."
-    exit 77
-fi
-
-if [ ! -f ../test-data/phony-guests/fedora.img ]; then
-    echo "$0: test skipped because fedora.img test guest does not exist."
-    exit 77
-fi
-
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because uml backend does not support qcow2"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped "test-fuse.sh"
+skip_if_skipped
+skip_unless_phony_guest fedora.img
+# UML backend does not support qcow2.
+skip_if_backend uml
+skip_unless_fuse
 
 rm -f test.qcow2 test-copy.qcow2 test.pid
 rm -rf mp
diff --git a/fuse/test-guestunmount-not-mounted.sh b/fuse/test-guestunmount-not-mounted.sh
index 7d65dba..5fb4a2e 100755
--- a/fuse/test-guestunmount-not-mounted.sh
+++ b/fuse/test-guestunmount-not-mounted.sh
@@ -20,27 +20,13 @@
 # Test that guestunmount returns the correct error code if
 # there is no mounted FUSE filesystem.
 
-unset CDPATH
-#set -e
-#set -v
-
-if [ -n "$SKIP_TEST_FUSE_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
-
-if [ -n "$SKIP_TEST_GUESTUNMOUNT_NOT_MOUNTED_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
-
-if [ ! -w /dev/fuse ]; then
-    echo "SKIPPING guestunmount test, because there is no /dev/fuse."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped "test-fuse.sh"
+skip_if_skipped
+skip_unless_fuse
 
 # Not expecting cwd to be a FUSE mountpoint.
-guestunmount --quiet $(pwd)
+guestunmount --quiet $abs_builddir
 r=$?
 case $r in
     0)
diff --git a/generator/fish.ml b/generator/fish.ml
index c2846d0..c3180be 100644
--- a/generator/fish.ml
+++ b/generator/fish.ml
@@ -1163,6 +1163,9 @@ and generate_fish_test_prep_sh () =
   pr "\
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 rm -f %s
 
 $VG guestfish \\
diff --git a/get-kernel/test-virt-get-kernel-docs.sh b/get-kernel/test-virt-get-kernel-docs.sh
index ab8d67f..7c45477 100755
--- a/get-kernel/test-virt-get-kernel-docs.sh
+++ b/get-kernel/test-virt-get-kernel-docs.sh
@@ -16,7 +16,9 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-$srcdir/../podcheck.pl virt-get-kernel.pod virt-get-kernel
+$TEST_FUNCTIONS
+skip_if_skipped
+
+$top_srcdir/podcheck.pl virt-get-kernel.pod virt-get-kernel
diff --git a/inspector/test-virt-inspector-docs.sh b/inspector/test-virt-inspector-docs.sh
index 8cd19ab..c9ad00b 100755
--- a/inspector/test-virt-inspector-docs.sh
+++ b/inspector/test-virt-inspector-docs.sh
@@ -16,7 +16,9 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-$srcdir/../podcheck.pl virt-inspector.pod virt-inspector
+$TEST_FUNCTIONS
+skip_if_skipped
+
+$top_srcdir/podcheck.pl virt-inspector.pod virt-inspector
diff --git a/inspector/test-virt-inspector.sh b/inspector/test-virt-inspector.sh
index 243783f..2f55cdc 100755
--- a/inspector/test-virt-inspector.sh
+++ b/inspector/test-virt-inspector.sh
@@ -16,15 +16,11 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 set -x
 
-# Allow this test to be skipped.
-if [ -n "$SKIP_TEST_VIRT_INSPECTOR_SH" ]; then
-    echo "$0: skipping test because SKIP_TEST_VIRT_INSPECTOR_SH is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
 
 # ntfs-3g can't set UUIDs right now, so ignore just that <uuid>.
 diff_ignore="-I <uuid>[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]</uuid>"
diff --git a/inspector/test-xmllint.sh.in b/inspector/test-xmllint.sh.in
index f269303..c5a5355 100755
--- a/inspector/test-xmllint.sh.in
+++ b/inspector/test-xmllint.sh.in
@@ -16,9 +16,11 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 for f in $srcdir/example-*.xml; do
     @XMLLINT@ --noout --relaxng $srcdir/virt-inspector.rng $f
 done
diff --git a/make-fs/test-virt-make-fs-docs.sh b/make-fs/test-virt-make-fs-docs.sh
index 70581d7..c6df103 100755
--- a/make-fs/test-virt-make-fs-docs.sh
+++ b/make-fs/test-virt-make-fs-docs.sh
@@ -16,7 +16,9 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-$srcdir/../podcheck.pl virt-make-fs.pod virt-make-fs --ignore=--debug
+$TEST_FUNCTIONS
+skip_if_skipped
+
+$top_srcdir/podcheck.pl virt-make-fs.pod virt-make-fs --ignore=--debug
diff --git a/make-fs/test-virt-make-fs.sh b/make-fs/test-virt-make-fs.sh
index 164ac9f..380e385 100755
--- a/make-fs/test-virt-make-fs.sh
+++ b/make-fs/test-virt-make-fs.sh
@@ -20,9 +20,11 @@
 # copied from the original Perl tool virt-make-fs, on the basis that
 # the new C tool should be able to pass the same tests.
 
-export LANG=C
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 # Check which filesystems are supported by the appliance.
 eval $(
 perl -MSys::Guestfs -e '
diff --git a/mllib/test-getopt.sh b/mllib/test-getopt.sh
index 3feafac..002bd10 100755
--- a/mllib/test-getopt.sh
+++ b/mllib/test-getopt.sh
@@ -22,6 +22,9 @@
 set -e
 set -x
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 t=./getopt_tests
 
 expect_fail ()
diff --git a/p2v/test-virt-p2v-cmdline.sh b/p2v/test-virt-p2v-cmdline.sh
index 9629a05..1584381 100755
--- a/p2v/test-virt-p2v-cmdline.sh
+++ b/p2v/test-virt-p2v-cmdline.sh
@@ -18,14 +18,10 @@
 
 # Test virt-p2v command line parsing in non-GUI mode.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_VIRT_P2V_CMDLINE_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
 
 out=test-virt-p2v-cmdline.out
 rm -f $out
diff --git a/p2v/test-virt-p2v-docs.sh b/p2v/test-virt-p2v-docs.sh
index c2d3585..5ef3c7f 100755
--- a/p2v/test-virt-p2v-docs.sh
+++ b/p2v/test-virt-p2v-docs.sh
@@ -16,7 +16,9 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-$srcdir/../podcheck.pl virt-p2v.pod virt-p2v
+$TEST_FUNCTIONS
+skip_if_skipped
+
+$top_srcdir/podcheck.pl virt-p2v.pod virt-p2v
diff --git a/p2v/test-virt-p2v-nbdkit.sh b/p2v/test-virt-p2v-nbdkit.sh
index 7044434..08e223b 100755
--- a/p2v/test-virt-p2v-nbdkit.sh
+++ b/p2v/test-virt-p2v-nbdkit.sh
@@ -18,38 +18,19 @@
 
 # Test virt-p2v in non-GUI mode using nbdkit instead of qemu-nbd.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_VIRT_P2V_NBDKIT_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
+skip_unless nbdkit file --version
+skip_unless_phony_guest windows.img
+skip_unless_phony_guest blank-part.img
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
+f1="$abs_top_builddir/test-data/phony-guests/windows.img"
+f2="$abs_top_builddir/test-data/phony-guests/blank-part.img"
 
-if ! nbdkit file --version; then
-    echo "$0: test skipped because nbdkit file plugin is not installed or not working"
-    exit 77
-fi
-
-guestsdir="$(cd ../test-data/phony-guests && pwd)"
-f1="$guestsdir/windows.img"
-if ! test -f $f1 || ! test -s $f1; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
-f2="$guestsdir/blank-part.img"
-if ! test -f $f2 || ! test -s $f2; then
-    echo "$0: test skipped because blank-part.img was not created"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
 
 d=test-virt-p2v-nbdkit.d
 rm -rf $d
diff --git a/p2v/test-virt-p2v-pxe.sh b/p2v/test-virt-p2v-pxe.sh
index bae6844..904f824 100755
--- a/p2v/test-virt-p2v-pxe.sh
+++ b/p2v/test-virt-p2v-pxe.sh
@@ -24,35 +24,16 @@
 # * networking
 # * virt-p2v in kernel command-line mode
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -z "$SLOW" ]; then
-    echo "$0: use 'make check-slow' to run this test"
-    exit 77
-fi
-
-if [ -n "$SKIP_TEST_VIRT_P2V_PXE_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
-
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
-
-if [ "$(uname -m)" != "x86_64" ]; then
-    echo "$0: test skipped because !x86_64"
-    exit 77
-fi
+$TEST_FUNCTIONS
+slow_test
+skip_if_skipped
+skip_if_backend uml
+skip_unless_arch x86_64
 
 qemu=qemu-system-x86_64
-if ! $qemu -help >/dev/null 2>&1; then
-    echo "$0: test skipped because $qemu not found"
-    exit 77
-fi
+skip_unless $qemu -help
 
 img="test-virt-p2v-pxe.img"
 if ! test -f $img; then
@@ -60,12 +41,8 @@ if ! test -f $img; then
     exit 77
 fi
 
-guestsdir="$(cd ../test-data/phony-guests && pwd)"
-f="$guestsdir/windows.img"
-if ! test -f $f; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
+skip_unless_phony_guest windows.img
+f="$top_builddir/test-data/phony-guests/windows.img"
 
 virt_tools_data_dir=${VIRT_TOOLS_DATA_DIR:-/usr/share/virt-tools}
 if ! test -r $virt_tools_data_dir/rhsrvany.exe; then
diff --git a/p2v/test-virt-p2v.sh b/p2v/test-virt-p2v.sh
index d464a46..3642dc0 100755
--- a/p2v/test-virt-p2v.sh
+++ b/p2v/test-virt-p2v.sh
@@ -18,33 +18,18 @@
 
 # Test virt-p2v in non-GUI mode.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_VIRT_P2V_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
+skip_unless_phony_guest windows.img
+skip_unless_phony_guest blank-part.img
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
+f1="$abs_top_builddir/test-data/phony-guests/windows.img"
+f2="$abs_top_builddir/test-data/phony-guests/blank-part.img"
 
-guestsdir="$(cd ../test-data/phony-guests && pwd)"
-f1="$guestsdir/windows.img"
-if ! test -f $f1 || ! test -s $f1; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
-f2="$guestsdir/blank-part.img"
-if ! test -f $f2 || ! test -s $f2; then
-    echo "$0: test skipped because blank-part.img was not created"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
 
 d=test-virt-p2v.d
 rm -rf $d
diff --git a/rescue/test-virt-rescue-docs.sh b/rescue/test-virt-rescue-docs.sh
index bdf647b..25f8f60 100755
--- a/rescue/test-virt-rescue-docs.sh
+++ b/rescue/test-virt-rescue-docs.sh
@@ -16,7 +16,9 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-$srcdir/../podcheck.pl virt-rescue.pod virt-rescue
+$TEST_FUNCTIONS
+skip_if_skipped
+
+$top_srcdir/podcheck.pl virt-rescue.pod virt-rescue
diff --git a/rescue/test-virt-rescue-suggest.sh b/rescue/test-virt-rescue-suggest.sh
index a8b41e2..609396c 100755
--- a/rescue/test-virt-rescue-suggest.sh
+++ b/rescue/test-virt-rescue-suggest.sh
@@ -16,15 +16,13 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-guest=../test-data/phony-guests/fedora.img
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_phony_guest fedora.img
 
-if [ ! -s "$guest" ]; then
-    echo "$0: test skipped because $guest does not exist or is an empty file"
-    exit 77
-fi
+guest="$top_builddir/test-data/phony-guests/fedora.img"
 
 rm -f virt-rescue-suggest.out
 
diff --git a/resize/test-virt-resize-docs.sh b/resize/test-virt-resize-docs.sh
index 407b486..8245655 100755
--- a/resize/test-virt-resize-docs.sh
+++ b/resize/test-virt-resize-docs.sh
@@ -16,8 +16,10 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-$srcdir/../podcheck.pl virt-resize.pod virt-resize \
+$TEST_FUNCTIONS
+skip_if_skipped
+
+$top_srcdir/podcheck.pl virt-resize.pod virt-resize \
     --ignore=--LVexpand,--lv-expand,--lvexpand,--dryrun
diff --git a/sparsify/test-virt-sparsify-docs.sh b/sparsify/test-virt-sparsify-docs.sh
index 9a16b43..2afca3b 100755
--- a/sparsify/test-virt-sparsify-docs.sh
+++ b/sparsify/test-virt-sparsify-docs.sh
@@ -16,8 +16,10 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-$srcdir/../podcheck.pl virt-sparsify.pod virt-sparsify \
-                       --ignore=--inplace
+$TEST_FUNCTIONS
+skip_if_skipped
+
+$top_srcdir/podcheck.pl virt-sparsify.pod virt-sparsify \
+                        --ignore=--inplace
diff --git a/sparsify/test-virt-sparsify-in-place-fstrim-unsupported.sh b/sparsify/test-virt-sparsify-in-place-fstrim-unsupported.sh
index b9fa96f..92d034e 100755
--- a/sparsify/test-virt-sparsify-in-place-fstrim-unsupported.sh
+++ b/sparsify/test-virt-sparsify-in-place-fstrim-unsupported.sh
@@ -29,19 +29,13 @@
 #
 # The reason why vfat is significant is because UEFI guests use it.
 
-export LANG=C
 set -e
 set -x
 
-if [ -n "$SKIP_TEST_VIRT_SPARSIFY_IN_PLACE_FSTRIM_UNSUPPORTED_SH" ]; then
-    echo "$0: skipping test (environment variable set)"
-    exit 77
-fi
-
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: skipping test because uml backend does not support discard"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+# UML does not support discard.
+skip_if_backend uml
 
 img=test-virt-sparsify-in-place-fstrim-unsupported.img
 log=test-virt-sparsify-in-place-fstrim-unsupported.log
diff --git a/sparsify/test-virt-sparsify-in-place.sh b/sparsify/test-virt-sparsify-in-place.sh
index 9d35eba..074bd76 100755
--- a/sparsify/test-virt-sparsify-in-place.sh
+++ b/sparsify/test-virt-sparsify-in-place.sh
@@ -16,18 +16,12 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_VIRT_SPARSIFY_IN_PLACE_SH" ]; then
-    echo "$0: skipping test (environment variable set)"
-    exit 77
-fi
-
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: skipping test because uml backend does not support discard"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+# UML does not support discard.
+skip_if_backend uml
 
 rm -f test-virt-sparsify-in-place.img
 
diff --git a/sparsify/test-virt-sparsify.sh b/sparsify/test-virt-sparsify.sh
index 7d18bf6..a3f0c92 100755
--- a/sparsify/test-virt-sparsify.sh
+++ b/sparsify/test-virt-sparsify.sh
@@ -16,13 +16,12 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: skipping test because uml backend does not support qcow2"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+# UML does not support qcow2.
+skip_if_backend uml
 
 rm -f test-virt-sparsify-1.img test-virt-sparsify-2.img
 
diff --git a/subdir-rules.mk b/subdir-rules.mk
index 4926c9c..61ab0d8 100644
--- a/subdir-rules.mk
+++ b/subdir-rules.mk
@@ -91,4 +91,20 @@ endif
 # Test shell scripts should use '$TEST_FUNCTIONS' to get a predefined
 # set of helper functions for running tests (see
 # tests/test-functions.sh).
-export TEST_FUNCTIONS := source $(abs_top_srcdir)/tests/test-functions.sh
+#
+# Notes:
+#
+# (1) This is in fact a single command all on one line.  The variables
+# are evaluated in test-functions.sh.
+#
+# (2) We use absolute paths here and in test-functions.sh so that the
+# test can change directory freely.  But we also include the
+# non-absolute values so they can be used by the test script itself.
+export TEST_FUNCTIONS := \
+	source $(abs_top_srcdir)/tests/test-functions.sh \
+	abs_srcdir="$(abs_srcdir)" \
+	abs_builddir="$(abs_builddir)" \
+	top_srcdir="$(top_srcdir)" \
+	top_builddir="$(top_builddir)" \
+	abs_top_srcdir="$(abs_top_srcdir)" \
+	abs_top_builddir="$(abs_top_builddir)"
diff --git a/sysprep/Makefile.am b/sysprep/Makefile.am
index bb8948d..2a1ca25 100644
--- a/sysprep/Makefile.am
+++ b/sysprep/Makefile.am
@@ -175,9 +175,6 @@ sysprep-operations.pod: virt-sysprep
 # Tests.
 
 TESTS_ENVIRONMENT = \
-	abs_builddir=$(abs_builddir) \
-	abs_srcdir=$(abs_srcdir) \
-	PATH=$(abs_top_builddir)/fuse:$(PATH) \
 	$(top_builddir)/run --test
 
 TESTS = \
diff --git a/sysprep/test-virt-sysprep-backup-files.sh b/sysprep/test-virt-sysprep-backup-files.sh
index 114e1d8..a05db15 100755
--- a/sysprep/test-virt-sysprep-backup-files.sh
+++ b/sysprep/test-virt-sysprep-backup-files.sh
@@ -16,20 +16,17 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
-set -e
-
 # Test removal of editor backup files.
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: skipping test because uml backend does not support qcow2"
-    exit 77
-fi
+set -e
+
+$TEST_FUNCTIONS
+skip_if_skipped
+# UML does not support qcow2.
+skip_if_backend uml
+skip_unless_phony_guest fedora.img
 
-if [ ! -s ../test-data/phony-guests/fedora.img ]; then
-    echo "$0: skipping test because there is no phony Fedora test image"
-    exit 77
-fi
+f=$top_builddir/test-data/phony-guests/fedora.img
 
 rm -f test-backup-files.qcow2
 rm -f test-backup-files-before
@@ -38,10 +35,9 @@ rm -f test-backup-files-after
 # Add some backup files to the Fedora image.
 guestfish -- \
           disk-create test-backup-files.qcow2 qcow2 -1 \
-            backingfile:../test-data/phony-guests/fedora.img \
-            backingformat:raw
+            backingfile:$f backingformat:raw
 guestfish --format=qcow2 -a test-backup-files.qcow2 -i <<'EOF'
-# /bin and /usr are not on the whitelist, so these file shouldn't be deleted.
+# /bin and /usr are not on the whitelist, so these files shouldn't be deleted.
 touch /bin/test~
 touch /usr/share/test~
 find / | cat > test-backup-files-before
diff --git a/sysprep/test-virt-sysprep-docs.sh b/sysprep/test-virt-sysprep-docs.sh
index c87bbb6..e950410 100755
--- a/sysprep/test-virt-sysprep-docs.sh
+++ b/sysprep/test-virt-sysprep-docs.sh
@@ -16,10 +16,12 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-$srcdir/../podcheck.pl virt-sysprep.pod virt-sysprep \
+$TEST_FUNCTIONS
+skip_if_skipped
+
+$top_srcdir/podcheck.pl virt-sysprep.pod virt-sysprep \
     --insert sysprep-extra-options.pod:__EXTRA_OPTIONS__ \
     --insert sysprep-operations.pod:__OPERATIONS__ \
     --ignore=--dryrun,--dump-pod,--dump-pod-options,--no-selinux-relabel
diff --git a/sysprep/test-virt-sysprep-passwords.sh b/sysprep/test-virt-sysprep-passwords.sh
index 5e185e3..9aefacd 100755
--- a/sysprep/test-virt-sysprep-passwords.sh
+++ b/sysprep/test-virt-sysprep-passwords.sh
@@ -16,20 +16,17 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
-set -e
-
 # Test all the combinations of password options.
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: skipping test because uml backend does not support qcow2"
-    exit 77
-fi
+set -e
+
+$TEST_FUNCTIONS
+skip_if_skipped
+# UML backend does not support qcow2.
+skip_if_backend uml
+skip_unless_phony_guest fedora.img
 
-if [ ! -s ../test-data/phony-guests/fedora.img ]; then
-    echo "$0: skipping test because there is no phony Fedora test image"
-    exit 77
-fi
+f=$top_builddir/test-data/phony-guests/fedora.img
 
 # For this test to work, we need a guest with several user accounts,
 # so we fake that now.
@@ -37,7 +34,7 @@ fi
 rm -f passwords.qcow2 password
 guestfish -- \
     disk-create passwords.qcow2 qcow2 -1 \
-      backingfile:../test-data/phony-guests/fedora.img backingformat:raw
+      backingfile:$f backingformat:raw
 
 guestfish -a passwords.qcow2 -i <<'EOF'
 write-append /etc/shadow "test01::15677:0:99999:7:::\n"
diff --git a/sysprep/test-virt-sysprep-script.sh b/sysprep/test-virt-sysprep-script.sh
index 49d0756..e8feaef 100755
--- a/sysprep/test-virt-sysprep-script.sh
+++ b/sysprep/test-virt-sysprep-script.sh
@@ -16,23 +16,22 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 #set -x
 
-if [ -n "$SKIP_TEST_VIRT_SYSPREP_SCRIPT_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_fuse
+skip_unless_phony_guest fedora.img
 
-if [ ! -w /dev/fuse ]; then
-    echo "$0: SKIPPING test, because there is no /dev/fuse."
-    exit 77
-fi
+f=$top_builddir/test-data/phony-guests/fedora.img
+
+# Export it down to the test scripts.
+export abs_builddir
 
 # Check that multiple scripts can run.
 rm -f stamp-script1.sh stamp-script2.sh stamp-script4.sh
-if ! virt-sysprep -q -n --format raw -a ../test-data/phony-guests/fedora.img --enable script \
+if ! virt-sysprep -q -n --format raw -a $f --enable script \
         --script $abs_srcdir/script1.sh --script $abs_srcdir/script2.sh; then
     echo "$0: virt-sysprep wasn't expected to exit with error."
     exit 1
@@ -43,19 +42,19 @@ if [ ! -f stamp-script1.sh -o ! -f stamp-script2.sh ]; then
 fi
 
 # Check that if a script fails, virt-sysprep exits with an error.
-if virt-sysprep -q -n --format raw -a ../test-data/phony-guests/fedora.img --enable script \
+if virt-sysprep -q -n --format raw -a $f --enable script \
         --script $abs_srcdir/script3.sh; then
     echo "$0: virt-sysprep didn't exit with an error."
     exit 1
 fi
 
 # Check that virt-sysprep uses a new temporary directory every time.
-if ! virt-sysprep -q -n --format raw -a ../test-data/phony-guests/fedora.img --enable script \
+if ! virt-sysprep -q -n --format raw -a $f --enable script \
         --script $abs_srcdir/script4.sh; then
     echo "$0: virt-sysprep (script4.sh, try #1) wasn't expected to exit with error."
     exit 1
 fi
-if ! virt-sysprep -q -n --format raw -a ../test-data/phony-guests/fedora.img --enable script \
+if ! virt-sysprep -q -n --format raw -a $f --enable script \
         --script $abs_srcdir/script4.sh; then
     echo "$0: virt-sysprep (script4.sh, try #2) wasn't expected to exit with error."
     exit 1
diff --git a/sysprep/test-virt-sysprep.sh b/sysprep/test-virt-sysprep.sh
index 802f9b6..40dd12a 100755
--- a/sysprep/test-virt-sysprep.sh
+++ b/sysprep/test-virt-sysprep.sh
@@ -16,13 +16,10 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_VIRT_SYSPREP_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
 
 # Get a comma-separated list of the enabled-by-default operations.
 operations=$(
diff --git a/tests/9p/Makefile.am b/tests/9p/Makefile.am
index 53538bf..30564f8 100644
--- a/tests/9p/Makefile.am
+++ b/tests/9p/Makefile.am
@@ -21,5 +21,5 @@ EXTRA_DIST = $(TESTS)
 
 TESTS = test-9p.sh
 
-TESTS_ENVIRONMENT = abs_srcdir=$(abs_srcdir) \
+TESTS_ENVIRONMENT = \
 	$(top_builddir)/run --test
diff --git a/tests/9p/test-9p.sh b/tests/9p/test-9p.sh
index 39b89b9..7486030 100755
--- a/tests/9p/test-9p.sh
+++ b/tests/9p/test-9p.sh
@@ -21,16 +21,9 @@
 
 set -e
 
-if [ -n "$SKIP_TEST_9P_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
-
-backend="$(guestfish get-backend)"
-if [[ "$backend" != "direct" ]]; then
-    echo "$0: test skipped because backend ($backend) is not 'direct'."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_backend direct
 
 # The name of the virtio-9p device is different on virtio-pci and virtio-mmio.
 arch="$(uname -m)"
diff --git a/tests/btrfs/test-btrfs-devices.sh b/tests/btrfs/test-btrfs-devices.sh
index 2cdf01f..dece32c 100755
--- a/tests/btrfs/test-btrfs-devices.sh
+++ b/tests/btrfs/test-btrfs-devices.sh
@@ -24,17 +24,9 @@
 
 set -e
 
-# Allow the test to be skipped since btrfs is often broken.
-if [ -n "$SKIP_TEST_BTRFS_DEVICES_SH" ]; then
-    echo "$0: skipping test because environment variable is set."
-    exit 77
-fi
-
-# If btrfs is not available, bail.
-if ! guestfish -a /dev/null run : available btrfs; then
-    echo "$0: skipping test because btrfs is not available"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_feature_available btrfs
 
 rm -f test-btrfs-devices-{1,2,3,4}.img
 
@@ -55,7 +47,7 @@ mkfs-btrfs "/dev/sda1 /dev/sdb1"
 mount /dev/sda1 /
 
 mkdir /data1
-tar-in $srcdir/../../test-data/files/filesanddirs-10M.tar.xz /data1 compress:xz
+tar-in $top_srcdir/test-data/files/filesanddirs-10M.tar.xz /data1 compress:xz
 
 # In btrfs-progs 0.19, a test was added which prevents us from
 # deleting the mount device (/dev/sda1) although that restriction
@@ -68,7 +60,7 @@ btrfs-device-add "/dev/sdb1" /
 btrfs-device-delete "/dev/sdc1 /dev/sdd1" /
 
 mkdir /data2
-tar-in $srcdir/../../test-data/files/filesanddirs-10M.tar.xz /data2 compress:xz
+tar-in $top_srcdir/test-data/files/filesanddirs-10M.tar.xz /data2 compress:xz
 
 btrfs-device-add "/dev/sdc1 /dev/sdd1" /
 btrfs-device-delete "/dev/sdb1" /
@@ -76,7 +68,7 @@ btrfs-device-add "/dev/sdb1" /
 btrfs-device-delete "/dev/sdc1 /dev/sdd1" /
 
 mkdir /data3
-tar-in $srcdir/../../test-data/files/filesanddirs-10M.tar.xz /data3 compress:xz
+tar-in $top_srcdir/test-data/files/filesanddirs-10M.tar.xz /data3 compress:xz
 
 btrfs-device-add "/dev/sdc1 /dev/sdd1" /
 btrfs-device-delete "/dev/sdb1" /
@@ -84,7 +76,7 @@ btrfs-device-add "/dev/sdb1" /
 btrfs-device-delete "/dev/sdc1 /dev/sdd1" /
 
 mkdir /data4
-tar-in $srcdir/../../test-data/files/filesanddirs-10M.tar.xz /data4 compress:xz
+tar-in $top_srcdir/test-data/files/filesanddirs-10M.tar.xz /data4 compress:xz
 
 btrfs-device-add "/dev/sdc1 /dev/sdd1" /
 btrfs-device-delete "/dev/sdb1" /
diff --git a/tests/btrfs/test-btrfs-replace.sh b/tests/btrfs/test-btrfs-replace.sh
index 77aeb46..68fe9a4 100755
--- a/tests/btrfs/test-btrfs-replace.sh
+++ b/tests/btrfs/test-btrfs-replace.sh
@@ -20,17 +20,9 @@
 
 set -e
 
-# Allow the test to be skipped since btrfs is often broken.
-if [ -n "$SKIP_TEST_BTRFS_REPLACE_SH" ]; then
-    echo "$0: skipping test because environment variable is set."
-    exit 77
-fi
-
-# If btrfs is not available, bail.
-if ! guestfish -a /dev/null run : available btrfs; then
-    echo "$0: skipping test because btrfs is not available"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_feature_available btrfs
 
 rm -f test-btrfs-replace-{1,2}.img replace.output
 
@@ -44,7 +36,7 @@ mkfs-btrfs /dev/sda
 mount /dev/sda /
 
 mkdir /data
-copy-in $srcdir/../../test-data/files/filesanddirs-10M.tar.xz /data
+copy-in $top_srcdir/test-data/files/filesanddirs-10M.tar.xz /data
 
 # now, sda is btrfs while sdb is blank.
 btrfs-replace /dev/sda /dev/sdb /
diff --git a/tests/create/test-disk-create.sh b/tests/create/test-disk-create.sh
index 6b8a6ef..e52f0f6 100755
--- a/tests/create/test-disk-create.sh
+++ b/tests/create/test-disk-create.sh
@@ -17,14 +17,10 @@
 
 # Test the disk-create API.
 
-export LANG=C
-
 set -e
 
-if [ -n "$SKIP_TEST_DISK_CREATE_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
 
 rm -f disk*.img file:*.img
 
diff --git a/tests/disks/Makefile.am b/tests/disks/Makefile.am
index ec95e82..477cec8 100644
--- a/tests/disks/Makefile.am
+++ b/tests/disks/Makefile.am
@@ -23,8 +23,6 @@ TESTS = \
 	test-qemu-drive.sh
 
 TESTS_ENVIRONMENT = \
-	abs_srcdir=$(abs_srcdir) \
-	abs_builddir=$(abs_builddir) \
 	$(top_builddir)/run --test
 
 EXTRA_DIST = \
diff --git a/tests/disks/test-qemu-drive-libvirt.sh b/tests/disks/test-qemu-drive-libvirt.sh
index 316a263..a1a7b89 100755
--- a/tests/disks/test-qemu-drive-libvirt.sh
+++ b/tests/disks/test-qemu-drive-libvirt.sh
@@ -17,29 +17,11 @@
 
 # Test that disks map to the correct qemu -drive parameter.
 
-export LANG=C
-
 set -e
 
-if [ -z "$abs_srcdir" ]; then
-    echo "$0: abs_srcdir environment variable must be set"
-    exit 1
-fi
-
-if [ -z "$abs_builddir" ]; then
-    echo "$0: abs_builddir environment variable must be set"
-    exit 1
-fi
-
-if [ ! -x ../../lib/libvirt-is-version ]; then
-    echo "$0: test skipped because libvirt-is-version is not built yet"
-    exit 77
-fi
-
-if ! ../../lib/libvirt-is-version 1 1 3; then
-    echo "$0: test skipped because libvirt is too old (< 1.1.3)"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_libvirt_minimum_version 1 1 3
 
 guestfish="guestfish -c test://$abs_builddir/test-qemu-drive-libvirt.xml"
 
diff --git a/tests/disks/test-qemu-drive.sh b/tests/disks/test-qemu-drive.sh
index bcb7841..19dd60a 100755
--- a/tests/disks/test-qemu-drive.sh
+++ b/tests/disks/test-qemu-drive.sh
@@ -17,13 +17,14 @@
 
 # Test that disks map to the correct qemu -drive parameter.
 
-export LANG=C
-
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 export LIBGUESTFS_BACKEND=direct
-export LIBGUESTFS_HV="${abs_srcdir}/debug-qemu.sh"
-export DEBUG_QEMU_FILE="${abs_builddir}/test-qemu-drive.out"
+export LIBGUESTFS_HV="$abs_srcdir/debug-qemu.sh"
+export DEBUG_QEMU_FILE="$abs_builddir/test-qemu-drive.out"
 
 function check_output ()
 {
diff --git a/tests/luks/test-luks-list.sh b/tests/luks/test-luks-list.sh
index be22e8b..0aceb14 100755
--- a/tests/luks/test-luks-list.sh
+++ b/tests/luks/test-luks-list.sh
@@ -20,16 +20,9 @@
 
 set -e
 
-[ -n "$SKIP_TEST_LUKS_SH" ] && {
-    echo "test-luks-list.sh skipped (environment variable set)"
-    exit 77
-}
-
-# If luks is not available, bail.
-if ! guestfish -a /dev/null run : available luks; then
-    echo "$0: skipping test because luks is not available"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_feature_available luks
 
 rm -f test-luks-list.img test-luks-list.out
 
diff --git a/tests/luks/test-luks.sh b/tests/luks/test-luks.sh
index 2f65750..9f58264 100755
--- a/tests/luks/test-luks.sh
+++ b/tests/luks/test-luks.sh
@@ -20,16 +20,9 @@
 
 set -e
 
-[ -n "$SKIP_TEST_LUKS_SH" ] && {
-    echo "test-luks.sh skipped (environment variable set)"
-    exit 77
-}
-
-# If luks is not available, bail.
-if ! guestfish -a /dev/null run : available luks; then
-    echo "$0: skipping test because luks is not available"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_feature_available luks
 
 rm -f test-luks.img
 
diff --git a/tests/lvm/test-lvm-filtering.sh b/tests/lvm/test-lvm-filtering.sh
index f00d712..0c8b880 100755
--- a/tests/lvm/test-lvm-filtering.sh
+++ b/tests/lvm/test-lvm-filtering.sh
@@ -20,10 +20,8 @@
 
 set -e
 
-if [ -n "$SKIP_TEST_LVM_FILTERING_SH" ]; then
-    echo "$0: skipping test because environment variable is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
 
 rm -f test-lvm-filtering-1.img test-lvm-filtering-2.img
 
diff --git a/tests/md/test-inspect-fstab-md.sh b/tests/md/test-inspect-fstab-md.sh
index 3c25dac..1744dfa 100755
--- a/tests/md/test-inspect-fstab-md.sh
+++ b/tests/md/test-inspect-fstab-md.sh
@@ -19,18 +19,17 @@
 # Test the handling of MD devices specified in /etc/fstab
 
 set -e
-export LANG=C
 
-if [ -n "$SKIP_TEST_INSPECT_FSTAB_MD_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_phony_guest fedora-md1.img
+skip_unless_phony_guest fedora-md2.img
 
 rm -f inspect-fstab-md-{1,2}.img inspect-fstab-md.fstab inspect-fstab-md.output
 
 # First, test the regular fedora image, which specifies /boot as /dev/md0
-cp ../../test-data/phony-guests/fedora-md1.img inspect-fstab-md-1.img
-cp ../../test-data/phony-guests/fedora-md2.img inspect-fstab-md-2.img
+cp $top_builddir/test-data/phony-guests/fedora-md1.img inspect-fstab-md-1.img
+cp $top_builddir/test-data/phony-guests/fedora-md2.img inspect-fstab-md-2.img
 
 guestfish -i --format=raw -a inspect-fstab-md-1.img --format=raw -a inspect-fstab-md-2.img <<'EOF' | sort > inspect-fstab-md.output
   exists /boot/grub/grub.conf
diff --git a/tests/md/test-inspect-fstab.sh b/tests/md/test-inspect-fstab.sh
index 0739193..dc3c431 100755
--- a/tests/md/test-inspect-fstab.sh
+++ b/tests/md/test-inspect-fstab.sh
@@ -20,14 +20,13 @@
 # This also tests: https://bugzilla.redhat.com/668574
 
 set -e
-export LANG=C
 
-canonical="sed -r s,/dev/[abce-ln-z]+d,/dev/sd,g"
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
+skip_unless_phony_guest fedora.img
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: skipping test because uml backend does not support qcow2"
-    exit 77
-fi
+canonical="sed -r s,/dev/[abce-ln-z]+d,/dev/sd,g"
 
 rm -f inspect-fstab-1.qcow2 inspect-fstab.fstab inspect-fstab.output
 
@@ -35,7 +34,8 @@ rm -f inspect-fstab-1.qcow2 inspect-fstab.fstab inspect-fstab.output
 # and then inspect it.
 guestfish -- \
   disk-create inspect-fstab-1.qcow2 qcow2 -1 \
-    backingfile:../../test-data/phony-guests/fedora.img backingformat:raw
+    backingfile:$top_builddir/test-data/phony-guests/fedora.img \
+    backingformat:raw
 
 cat <<'EOF' > inspect-fstab.fstab
 /dev/VG/Root / ext2 default 0 0
diff --git a/tests/md/test-list-filesystems.sh b/tests/md/test-list-filesystems.sh
index 2bfa6f3..073a355 100755
--- a/tests/md/test-list-filesystems.sh
+++ b/tests/md/test-list-filesystems.sh
@@ -20,10 +20,8 @@
 
 set -e
 
-if [ -n "$SKIP_TEST_LIST_FILESYSTEMS_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
 
 rm -f list-fs.output
 
diff --git a/tests/md/test-list-md-devices.sh b/tests/md/test-list-md-devices.sh
index 3019f33..b7db10a 100755
--- a/tests/md/test-list-md-devices.sh
+++ b/tests/md/test-list-md-devices.sh
@@ -20,10 +20,8 @@
 
 set -e
 
-if [ -n "$SKIP_TEST_LIST_MD_DEVICES_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 0
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
 
 output=$(
 guestfish <<EOF
diff --git a/tests/md/test-mdadm.sh b/tests/md/test-mdadm.sh
index 05b2432..10a6939 100755
--- a/tests/md/test-mdadm.sh
+++ b/tests/md/test-mdadm.sh
@@ -20,10 +20,8 @@
 
 set -e
 
-if [ -n "$SKIP_TEST_MDADM_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
 
 rm -f mdadm-{1,2,3,4}.img
 
diff --git a/tests/mountable/test-mountable-inspect.sh b/tests/mountable/test-mountable-inspect.sh
index fcc184d..b7c9da6 100755
--- a/tests/mountable/test-mountable-inspect.sh
+++ b/tests/mountable/test-mountable-inspect.sh
@@ -17,26 +17,13 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
 set -e
-export LANG=C
 
-canonical="sed s,/dev/vd,/dev/sd,g"
-
-# Allow the test to be skipped since btrfs is often broken.
-if [ -n "$SKIP_TEST_MOUNTABLE_INSPECT_SH" ]; then
-    echo "$0: skipping test because environment variable is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
+skip_unless_feature_available btrfs
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: skipping test because uml backend does not support qcow2"
-    exit 77
-fi
-
-# Bail if btrfs is not available.
-if ! guestfish -a /dev/null run : available btrfs; then
-    echo "$0: skipping test because btrfs is not available"
-    exit 77
-fi
+canonical="sed s,/dev/vd,/dev/sd,g"
 
 rm -f root.tmp test.qcow2 test.output
 
diff --git a/tests/network/test-network.sh b/tests/network/test-network.sh
index 51f3667..55e0f96 100755
--- a/tests/network/test-network.sh
+++ b/tests/network/test-network.sh
@@ -21,17 +21,9 @@
 # test that the network device can be added.
 
 set -e
-export LANG=C
 
-if [ -n "$SKIP_TEST_NETWORK_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
-
-backend="$(guestfish get-backend)"
-if [[ "$backend" =~ ^uml ]]; then
-    echo "$0: test skipped because backend ($backend) is 'uml'."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
 
 guestfish --network -a /dev/null run
diff --git a/tests/ntfs/test-ntfscat.sh b/tests/ntfs/test-ntfscat.sh
index 50f4dca..9fece4d 100755
--- a/tests/ntfs/test-ntfscat.sh
+++ b/tests/ntfs/test-ntfscat.sh
@@ -20,26 +20,16 @@
 
 set -e
 
-if [ -n "$SKIP_TEST_NTFSCAT_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_feature_available ntfs3g
+skip_unless_phony_guest windows.img
 
 rm -f test-mft.bin
 
-# Skip if ntfs-3g is not supported by the appliance.
-if ! guestfish add /dev/null : run : available "ntfs3g"; then
-    echo "$0: skipped because ntfs-3g is not supported by the appliance"
-    exit 77
-fi
-
-if [ ! -s ../../test-data/phony-guests/windows.img ]; then
-    echo "$0: skipped because windows.img is zero-sized"
-    exit 77
-fi
-
-# download Master File Table ($MFT).
-guestfish --ro --format=raw -a ../../test-data/phony-guests/windows.img <<EOF
+# Download Master File Table ($MFT).
+guestfish \
+    --ro --format=raw -a $top_builddir/test-data/phony-guests/windows.img <<EOF
 run
 ntfscat-i /dev/sda2 0 test-mft.bin
 EOF
diff --git a/tests/ntfs/test-ntfsclone.sh b/tests/ntfs/test-ntfsclone.sh
index b403670..ba948e0 100755
--- a/tests/ntfs/test-ntfsclone.sh
+++ b/tests/ntfs/test-ntfsclone.sh
@@ -20,26 +20,16 @@
 
 set -e
 
-if [ -n "$SKIP_TEST_NTFSCLONE_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_feature_available ntfs3g
+skip_unless_phony_guest windows.img
 
 rm -f test-ntfsclone.img ntfsclone-backup1 ntfsclone-backup2
 
-# Skip if ntfs-3g is not supported by the appliance.
-if ! guestfish add /dev/null : run : available "ntfs3g"; then
-    echo "$0: skipped because ntfs-3g is not supported by the appliance"
-    exit 77
-fi
-
-if [ ! -s ../../test-data/phony-guests/windows.img ]; then
-    echo "$0: skipped because windows.img is zero-sized"
-    exit 77
-fi
-
 # Export the filesystems to the backup file.
-guestfish --ro --format=raw -a ../../test-data/phony-guests/windows.img <<EOF
+guestfish \
+    --ro --format=raw -a $top_builddir/test-data/phony-guests/windows.img <<EOF
 run
 ntfsclone-out /dev/sda1 ntfsclone-backup1 preservetimestamps:true force:true
 ntfsclone-out /dev/sda2 ntfsclone-backup2 metadataonly:true ignorefscheck:true
diff --git a/tests/protocol/test-both-ends-cancel.sh b/tests/protocol/test-both-ends-cancel.sh
index 6301186..dc1475a 100755
--- a/tests/protocol/test-both-ends-cancel.sh
+++ b/tests/protocol/test-both-ends-cancel.sh
@@ -22,6 +22,9 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 guestfish <<EOF
 scratch 100M
 run
diff --git a/tests/protocol/test-cancellation-download-librarycancels.sh b/tests/protocol/test-cancellation-download-librarycancels.sh
index ddaa87d..b89612d 100755
--- a/tests/protocol/test-cancellation-download-librarycancels.sh
+++ b/tests/protocol/test-cancellation-download-librarycancels.sh
@@ -26,6 +26,9 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 tmpfile=`mktemp`
 
 size=$(awk 'BEGIN{ srand(); print int(16*1024*rand()) }')
diff --git a/tests/protocol/test-cancellation-upload-daemoncancels.sh b/tests/protocol/test-cancellation-upload-daemoncancels.sh
index f789037..129f4e8 100755
--- a/tests/protocol/test-cancellation-upload-daemoncancels.sh
+++ b/tests/protocol/test-cancellation-upload-daemoncancels.sh
@@ -22,6 +22,9 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 guestfish \
     -N test-cancellation-upload-daemoncancels.img=fs:ext2:10M \
     -m /dev/sda1 <<'EOF'
diff --git a/tests/protocol/test-qemudie-killsub.sh b/tests/protocol/test-qemudie-killsub.sh
index 45e8b2d..b72cfde 100755
--- a/tests/protocol/test-qemudie-killsub.sh
+++ b/tests/protocol/test-qemudie-killsub.sh
@@ -20,10 +20,9 @@
 
 set -e
 
-if [ "$(guestfish get-backend)" != "direct" ]; then
-    echo "$0: test skipped because default backend is not 'direct'"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_backend direct
 
 guestfish <<'EOF'
 scratch 100M
diff --git a/tests/protocol/test-qemudie-midcommand.sh b/tests/protocol/test-qemudie-midcommand.sh
index 058df2c..7578bc2 100755
--- a/tests/protocol/test-qemudie-midcommand.sh
+++ b/tests/protocol/test-qemudie-midcommand.sh
@@ -20,10 +20,9 @@
 
 set -e
 
-if [ "$(guestfish get-backend)" != "direct" ]; then
-    echo "$0: test skipped because default backend is not 'direct'"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_backend direct
 
 rm -f qemudie-midcommand.pid
 
diff --git a/tests/protocol/test-qemudie-synch.sh b/tests/protocol/test-qemudie-synch.sh
index a7066ed..25cde5e 100755
--- a/tests/protocol/test-qemudie-synch.sh
+++ b/tests/protocol/test-qemudie-synch.sh
@@ -20,10 +20,9 @@
 
 set -e
 
-if [ "$(guestfish get-backend)" != "direct" ]; then
-    echo "$0: test skipped because default backend is not 'direct'"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_backend direct
 
 rm -f qemudie-synch.pid
 
diff --git a/tests/qemu/qemu-force-tcg.sh b/tests/qemu/qemu-force-tcg.sh
index 79b32b7..d540102 100755
--- a/tests/qemu/qemu-force-tcg.sh
+++ b/tests/qemu/qemu-force-tcg.sh
@@ -18,16 +18,10 @@
 
 # Check force_tcg really forces TCG mode.
 
-if [ -n "$SKIP_QEMU_FORCE_TCG_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
-
-# Only applicable to the direct and libvirt backends:
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: skipping test because it is only applicable when qemu is being used."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+# Only applicable if the backend uses qemu.
+skip_if_backend uml
 
 set -e
 
diff --git a/tests/qemu/qemu-liveness.sh b/tests/qemu/qemu-liveness.sh
index c9b79f0..1a8db82 100755
--- a/tests/qemu/qemu-liveness.sh
+++ b/tests/qemu/qemu-liveness.sh
@@ -23,6 +23,7 @@
 set -e
 
 $TEST_FUNCTIONS
+skip_if_skipped
 
 rm -f liveness1.img
 
diff --git a/tests/qemu/qemu-snapshot-isolation.sh b/tests/qemu/qemu-snapshot-isolation.sh
index d72ff9f..3406b2a 100755
--- a/tests/qemu/qemu-snapshot-isolation.sh
+++ b/tests/qemu/qemu-snapshot-isolation.sh
@@ -23,6 +23,7 @@
 set -e
 
 $TEST_FUNCTIONS
+skip_if_skipped
 
 # UML backend doesn't support qcow2 format.
 supports_qcow2=yes
diff --git a/tests/regressions/rhbz1001875.sh b/tests/regressions/rhbz1001875.sh
index 885fd8c..d9d19a2 100755
--- a/tests/regressions/rhbz1001875.sh
+++ b/tests/regressions/rhbz1001875.sh
@@ -21,12 +21,9 @@
 # tar-out excludes option.
 
 set -e
-export LANG=C
 
-if [ -n "$SKIP_TEST_RHBZ1001875_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
 
 rm -f rhbz1001875.img rhbz1001875-[123].tar
 
diff --git a/tests/regressions/rhbz1011907-1165785.sh b/tests/regressions/rhbz1011907-1165785.sh
index ac3b49d..ac40435 100755
--- a/tests/regressions/rhbz1011907-1165785.sh
+++ b/tests/regressions/rhbz1011907-1165785.sh
@@ -23,12 +23,9 @@
 # of base devices (like /dev/loop-control for loopback setup)
 
 set -e
-export LANG=C
 
-if [ -n "$SKIP_TEST_RHBZ1011907_1165785_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
 
 rm -f rhbz1011907-1165785-loop.img rhbz1011907-1165785.img
 
diff --git a/tests/regressions/rhbz1044014.sh b/tests/regressions/rhbz1044014.sh
index f9e0455..c021ce1 100755
--- a/tests/regressions/rhbz1044014.sh
+++ b/tests/regressions/rhbz1044014.sh
@@ -20,32 +20,14 @@
 # https://bugzilla.redhat.com/show_bug.cgi?id=1044014
 
 set -e
-export LANG=C
 
-if [ -n "$SKIP_TEST_RHBZ1044014_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
-
-# Check we are running against the libvirt backend.
-backend="$(guestfish get-backend)"
-if [[ ! ( "$backend" =~ ^libvirt ) ]]; then
-    echo "$0: test skipped because backend ($backend) is not libvirt."
-    exit 77
-fi
-
-if [ ! -x ../../lib/libvirt-is-version ]; then
-    echo "$0: test skipped because libvirt-is-version is not built yet"
-    exit 77
-fi
-
-if ! ../../lib/libvirt-is-version 1 2 1; then
-    echo "$0: test skipped because libvirt is too old (< 1.2.1)"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_backend libvirt
+skip_unless_libvirt_minimum_version 1 2 1
 
 # Set the backend to the test driver.
-export LIBGUESTFS_BACKEND="libvirt:test://$(pwd)/$srcdir/rhbz1044014.xml"
+export LIBGUESTFS_BACKEND="libvirt:test://$abs_srcdir/rhbz1044014.xml"
 
 rm -f rhbz1044014.out
 
diff --git a/tests/regressions/rhbz1054761.sh b/tests/regressions/rhbz1054761.sh
index 1b414f2..1b7ec89 100755
--- a/tests/regressions/rhbz1054761.sh
+++ b/tests/regressions/rhbz1054761.sh
@@ -21,12 +21,9 @@
 # Handle broken/missing PVs gracefully.
 
 set -e
-export LANG=C
 
-if [ -n "$SKIP_TEST_RHBZ1054761_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
 
 rm -f rhbz1054761-[ab].img
 
diff --git a/tests/regressions/rhbz1091803.sh b/tests/regressions/rhbz1091803.sh
index 6851a1c..2c0bb75 100755
--- a/tests/regressions/rhbz1091803.sh
+++ b/tests/regressions/rhbz1091803.sh
@@ -21,12 +21,9 @@
 # tar-in API didn't cancel the receive correctly along all error paths.
 
 set -e
-export LANG=C
 
-if [ -n "$SKIP_TEST_RHBZ1091803_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
 
 guestfish <<EOF
 scratch 100M
diff --git a/tests/regressions/rhbz1174551.sh b/tests/regressions/rhbz1174551.sh
index 4594657..b55d8bb 100755
--- a/tests/regressions/rhbz1174551.sh
+++ b/tests/regressions/rhbz1174551.sh
@@ -22,21 +22,16 @@
 # absolute ones
 
 set -e
-export LANG=C
 
-if [ -n "$SKIP_TEST_RHBZ1174551_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
-
-if [ ! -s ../../test-data/phony-guests/fedora.img ]; then
-    echo "$0: test skipped because there is no fedora.img"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_phony_guest fedora.img
 
 rm -f test.error
 
-$VG guestfish --ro --format=raw -a ../../test-data/phony-guests/fedora.img -i <<EOF 2>test.error
+$VG guestfish \
+    --ro --format=raw -a $top_builddir/test-data/phony-guests/fedora.img \
+    -i <<EOF 2>test.error
 # valid invocations
 lstatlist /etc "fedora-release sysconfig"
 lstatnslist /etc "fedora-release sysconfig"
diff --git a/tests/regressions/rhbz1175196.sh b/tests/regressions/rhbz1175196.sh
index e88f447..8b2db9e 100755
--- a/tests/regressions/rhbz1175196.sh
+++ b/tests/regressions/rhbz1175196.sh
@@ -21,7 +21,9 @@
 # Parse 'LIBGUESTFS_TRACE=0' in the environment.
 
 set -e
-export LANG=C
+
+$TEST_FUNCTIONS
+skip_if_skipped
 
 output="$(guestfish <<EOF
 
diff --git a/tests/regressions/rhbz1232192.sh b/tests/regressions/rhbz1232192.sh
index 134c381..2d4b342 100755
--- a/tests/regressions/rhbz1232192.sh
+++ b/tests/regressions/rhbz1232192.sh
@@ -20,33 +20,14 @@
 # https://bugzilla.redhat.com/show_bug.cgi?id=1232192
 
 set -e
-export LANG=C
 
-if [ -n "$SKIP_TEST_RHBZ1232192_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless virt-v2v --help
+skip_if_backend uml
+skip_unless_phony_guest windows.img
+skip_unless_phony_guest blank-disk.img
 
-if ! ../../v2v/virt-v2v --help >/dev/null 2>&1; then
-    echo "$0: test skipped because virt-v2v was not built"
-    exit 77
-fi
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
-
-if [ ! -f ../../test-data/phony-guests/windows.img ] || [ ! -s ../../test-data/phony-guests/windows.img ]; then
-    echo "$0: test skipped because test-data/phony-guests/windows.img was not built"
-    exit 77
-fi
-
-if [ ! -f ../../test-data/phony-guests/blank-disk.img ]; then
-    echo "$0: test skipped because test-data/phony-guests/blank-disk.img was not built"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../../test-data/fake-virt-tools"
-
-../../v2v/virt-v2v -i libvirtxml rhbz1232192.xml -o null --no-copy
+virt-v2v -i libvirtxml rhbz1232192.xml -o null --no-copy
diff --git a/tests/regressions/rhbz1285847.sh b/tests/regressions/rhbz1285847.sh
index b72ec89..1bfb9fc 100755
--- a/tests/regressions/rhbz1285847.sh
+++ b/tests/regressions/rhbz1285847.sh
@@ -20,17 +20,10 @@
 # https://bugzilla.redhat.com/1285847
 
 set -e
-export LANG=C
 
-if [ -n "$SKIP_TEST_RHBZ1285847_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
-
-if ! ../../resize/virt-resize --help >/dev/null 2>&1; then
-    echo "$0: test skipped because virt-resize was not built"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless virt-resize --help
 
 rm -f rhbz1285847.img rhbz1285847-2.img rhbz1285847.out
 
diff --git a/tests/regressions/rhbz1370424.sh b/tests/regressions/rhbz1370424.sh
index 5b21a32..c28cf3a 100755
--- a/tests/regressions/rhbz1370424.sh
+++ b/tests/regressions/rhbz1370424.sh
@@ -21,17 +21,10 @@
 # Handle a network disk without a port attribute.
 
 set -e
-export LANG=C
 
-if [ -n "$SKIP_TEST_RHBZ1370424_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
-
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
 
 guestfish <<EOF
 -add-domain rhbz1370424 \
diff --git a/tests/regressions/rhbz503169c13.sh b/tests/regressions/rhbz503169c13.sh
index b0ee77b..dfdc30b 100755
--- a/tests/regressions/rhbz503169c13.sh
+++ b/tests/regressions/rhbz503169c13.sh
@@ -26,6 +26,9 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 guestfish -N rhbz503169c13.img=fs -m /dev/sda1 <<EOF
 mkdir /dev
 -command /ignore-this-error
diff --git a/tests/regressions/rhbz557655.sh b/tests/regressions/rhbz557655.sh
index fd723bf..1dd8e36 100755
--- a/tests/regressions/rhbz557655.sh
+++ b/tests/regressions/rhbz557655.sh
@@ -21,8 +21,11 @@
 # "guestfish number parsing should not use atoi, should support '0...' for octal and '0x...' for hexadecimal"
 
 set -e
+
+$TEST_FUNCTIONS
+skip_if_skipped
+
 rm -f rhbz557655.out rhbz557655.err
-export LANG=C
 
 guestfish >> rhbz557655.out 2>> rhbz557655.err <<EOF
 # set-memsize is just a convenient non-daemon function that
diff --git a/tests/regressions/rhbz563450.sh b/tests/regressions/rhbz563450.sh
index 3c53da6..3b39fba 100755
--- a/tests/regressions/rhbz563450.sh
+++ b/tests/regressions/rhbz563450.sh
@@ -20,19 +20,19 @@
 # Test the order of added images
 
 set -e
-export LANG=C
 
-if [ ! -s ../../test-data/phony-guests/fedora.img -o ! -s ../../test-data/test.iso -o ! -s ../../test-data/phony-guests/debian.img ]; then
-    echo "$0: test skipped because there is no fedora.img nor test.iso nor debian.img"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_phony_guest fedora.img
+skip_unless_phony_guest debian.img
+skip_unless_test_iso
 
 rm -f rhbz563450.out
 
 guestfish --ro > rhbz563450.out <<EOF
-add ../../test-data/phony-guests/fedora.img readonly:true format:raw
-add-cdrom ../../test-data/test.iso
-add ../../test-data/phony-guests/debian.img readonly:true format:raw
+add $top_builddir/test-data/phony-guests/fedora.img readonly:true format:raw
+add-cdrom $top_builddir/test-data/test.iso
+add $top_builddir/test-data/phony-guests/debian.img readonly:true format:raw
 
 run
 
diff --git a/tests/regressions/rhbz563450b.sh b/tests/regressions/rhbz563450b.sh
index 30f07b0..a265949 100755
--- a/tests/regressions/rhbz563450b.sh
+++ b/tests/regressions/rhbz563450b.sh
@@ -20,12 +20,10 @@
 # Test only CD-ROM disk images can be added
 
 set -e
-export LANG=C
 
-if [ ! -s ../../test-data/test.iso ]; then
-    echo "$0: test skipped because there is no test.iso"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_test_iso
 
 rm -f rhbz563450b.out
 
diff --git a/tests/regressions/rhbz576879.sh b/tests/regressions/rhbz576879.sh
index fece6b4..4ace7f7 100755
--- a/tests/regressions/rhbz576879.sh
+++ b/tests/regressions/rhbz576879.sh
@@ -22,6 +22,9 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 guestfish <<EOF
 scratch 100M
 run
diff --git a/tests/regressions/rhbz578407.sh b/tests/regressions/rhbz578407.sh
index fb7ba93..6f5de92 100755
--- a/tests/regressions/rhbz578407.sh
+++ b/tests/regressions/rhbz578407.sh
@@ -23,6 +23,9 @@
 
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+
 # Start remote guestfish.
 eval `guestfish --listen 2>/dev/null`
 
diff --git a/tests/regressions/rhbz580246.sh b/tests/regressions/rhbz580246.sh
index 8b842e5..ee03fbb 100755
--- a/tests/regressions/rhbz580246.sh
+++ b/tests/regressions/rhbz580246.sh
@@ -21,7 +21,9 @@
 # https://bugzilla.redhat.com/show_bug.cgi?id=580246
 
 set -e
-export LANG=C
+
+$TEST_FUNCTIONS
+skip_if_skipped
 
 rm -f rhbz580246.img rhbz580246.tar
 
diff --git a/tests/regressions/rhbz602997.sh b/tests/regressions/rhbz602997.sh
index d48693b..d49e74a 100755
--- a/tests/regressions/rhbz602997.sh
+++ b/tests/regressions/rhbz602997.sh
@@ -20,7 +20,9 @@
 # Fix part-get-bootable to work with missing/unordered partitions.
 
 set -e
-export LANG=C
+
+$TEST_FUNCTIONS
+skip_if_skipped
 
 rm -f test.output
 
diff --git a/tests/regressions/rhbz727178.sh b/tests/regressions/rhbz727178.sh
index 639fc32..79dceaa 100755
--- a/tests/regressions/rhbz727178.sh
+++ b/tests/regressions/rhbz727178.sh
@@ -21,7 +21,9 @@
 # corresponding libraries.
 
 set -e
-export LANG=C
+
+$TEST_FUNCTIONS
+skip_if_skipped
 
 output=rhbz727178.output
 
diff --git a/tests/regressions/rhbz789960.sh b/tests/regressions/rhbz789960.sh
index 0f9e4eb..22279df 100755
--- a/tests/regressions/rhbz789960.sh
+++ b/tests/regressions/rhbz789960.sh
@@ -20,11 +20,16 @@
 # Test the mount command error paths.
 
 set -e
-export LANG=C
+
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_phony_guest fedora.img
 
 rm -f rhbz789960.out
 
-guestfish --format=raw -a ../../test-data/phony-guests/fedora.img --ro > rhbz789960.out <<EOF
+guestfish \
+    --format=raw -a $top_builddir/test-data/phony-guests/fedora.img \
+    --ro > rhbz789960.out <<EOF
 run
 
 # Not a device at all, should fail.
diff --git a/tests/regressions/rhbz811649.sh b/tests/regressions/rhbz811649.sh
index 53064c0..a68ea67 100755
--- a/tests/regressions/rhbz811649.sh
+++ b/tests/regressions/rhbz811649.sh
@@ -20,7 +20,9 @@
 # Test filenames containing a variety of characters.
 
 set -e
-export LANG=C
+
+$TEST_FUNCTIONS
+skip_if_skipped
 
 declare -a filenames
 filenames[0]=' '
diff --git a/tests/regressions/rhbz895904.sh b/tests/regressions/rhbz895904.sh
index fb7dae9..8ab8c61 100755
--- a/tests/regressions/rhbz895904.sh
+++ b/tests/regressions/rhbz895904.sh
@@ -21,7 +21,9 @@
 # Ensure we have a test of the 'checksums-out' command.
 
 set -e
-export LANG=C
+
+$TEST_FUNCTIONS
+skip_if_skipped
 
 rm -f rhbz895904.img rhbz895904.out
 
diff --git a/tests/regressions/rhbz909624.sh b/tests/regressions/rhbz909624.sh
index ecc803c..066c563 100755
--- a/tests/regressions/rhbz909624.sh
+++ b/tests/regressions/rhbz909624.sh
@@ -24,12 +24,10 @@
 # libguestfs).
 
 set -e
-export LANG=C
 
-if [ -z "$SLOW" ]; then
-    echo "$0: use 'make check-slow' to run this test"
-    exit 77
-fi
+$TEST_FUNCTIONS
+slow_test
+skip_if_skipped
 
 guestfish <<EOF
 
diff --git a/tests/regressions/rhbz957772.sh b/tests/regressions/rhbz957772.sh
index 553cab8..e71ccb6 100755
--- a/tests/regressions/rhbz957772.sh
+++ b/tests/regressions/rhbz957772.sh
@@ -21,7 +21,9 @@
 # Ensure that tar-out and base64-out commands properly quote arguments.
 
 set -e
-export LANG=C
+
+$TEST_FUNCTIONS
+skip_if_skipped
 
 guestfish -N rhbz957772.img=fs -m /dev/sda1 <<EOF
 mkdir "/test 1"
diff --git a/tests/regressions/rhbz975797.sh b/tests/regressions/rhbz975797.sh
index c067a12..bc6a1c6 100755
--- a/tests/regressions/rhbz975797.sh
+++ b/tests/regressions/rhbz975797.sh
@@ -21,33 +21,17 @@
 # Ensure the appliance doesn't hang when using the 'iface' parameter.
 
 set -e
-export LANG=C
 
-if [ -n "$SKIP_TEST_RHBZ975797_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
-
-arch="$(uname -m)"
-if [[ "$arch" =~ ^arm || "$arch" = "aarch64" ]]; then
-    echo "$0: test skipped because ARM does not support 'ide' interface."
-    exit 77
-fi
-if [[ "$arch" =~ ^ppc ]]; then
-    echo "$0: test skipped because PowerPC does not support 'ide' interface."
-    exit 77
-fi
-
-backend="$(guestfish get-backend)"
-if [[ "$backend" =~ ^libvirt ]]; then
-    echo "$0: test skipped because backend ($backend) is 'libvirt'."
-    exit 77
-fi
-
-if [ "$backend" = "uml" ]; then
-    echo "$0: test skipped because uml backend does not support 'iface' param."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+# These architectures don't support the 'ide' interface.
+skip_if_arch arm
+skip_if_arch aarch64
+skip_if_arch ppc64
+skip_if_arch ppc64le
+skip_if_backend libvirt
+# UML doesn't support the 'iface' parameter.
+skip_if_backend uml
 
 rm -f rhbz975797-*.img
 
diff --git a/tests/relative-paths/test-relative-paths.sh b/tests/relative-paths/test-relative-paths.sh
index 4924cc3..3792259 100755
--- a/tests/relative-paths/test-relative-paths.sh
+++ b/tests/relative-paths/test-relative-paths.sh
@@ -18,17 +18,12 @@
 
 set -e
 
-if [ -n "$SKIP_TEST_RELATIVE_PATHS_SH" ]; then
-    echo "$0: skipped (environment variable set)"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
 
 # UML doesn't support qcow2.  Conceivably there might be a similar
 # problem with UML COW images which would require a separate test.
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: skipping test because uml backend does not support qcow2"
-    exit 77
-fi
+skip_if_backend uml
 
 rm -f backing*
 rm -f overlay*
diff --git a/tests/rsync/test-rsync.sh b/tests/rsync/test-rsync.sh
index c7bfa24..c6d98cf 100755
--- a/tests/rsync/test-rsync.sh
+++ b/tests/rsync/test-rsync.sh
@@ -19,19 +19,12 @@
 # Test rsync by copying a local directory using an involved and
 # unrealistic method.
 
-unset CDPATH
 set -e
 
-if [ -n "$SKIP_TEST_RSYNC_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
-
-# Check we have the rsync command.
-if ! rsync --help >/dev/null 2>&1; then
-    echo "$0: skipping test because local rsync command is not available"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless rsync --help
+skip_unless_feature_available rsync
 
 # Get host IP address.  XXX Bit of a hack.
 backend="$(guestfish get-backend)"
@@ -61,12 +54,6 @@ case "$backend" in
         ;;
 esac
 
-# If rsync is not available, bail.
-if ! guestfish -a /dev/null run : available rsync; then
-    echo "$0: skipping test because rsync is not available in the appliance"
-    exit 77
-fi
-
 pwd="$(pwd)"
 datadir="$(cd ../../test-data/files && pwd)"
 
diff --git a/tests/test-functions.sh b/tests/test-functions.sh
index 86a5aaf..74ad2ef 100755
--- a/tests/test-functions.sh
+++ b/tests/test-functions.sh
@@ -1,6 +1,6 @@
 #!/bin/bash -
 # libguestfs
-# Copyright (C) 2014 Red Hat Inc.
+# Copyright (C) 2014-2017 Red Hat Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -16,6 +16,232 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
+# Most of the tests written in shell script source this file for
+# useful functions.
+#
+# To include this file, the test must do:
+#
+#   $TEST_FUNCTIONS
+#
+# (this macro is defined in subdir-rules.mk).
+
+# Clean up the environment in every test script.
+unset CDPATH
+export LANG=C
+
+# When test-functions.sh is invoked, a list of variables is passed as
+# parameters, so we eval those to define the variables.
+while [ $# -ge 1 ]; do eval "$1"; shift; done
+
+# Skip if $SKIP_<script_name> environment variable is set.
+# Every test should call this function first.
+skip_if_skipped ()
+{
+    local v
+    if [ -n "$1" ]; then
+        v="SKIP_$(basename $1 | tr a-z.- A-Z__)"
+    else
+        v="SKIP_$(basename $0 | tr a-z.- A-Z__)"
+    fi
+    if [ -n "${!v}" ]; then
+        echo "$(basename $0): test skipped because \$$v is set"
+        exit 77
+    fi
+    echo "$(basename $0): info: you can skip this test by setting $v=1"
+}
+
+# Skip if the current libguestfs backend is $1.
+# eg. skip_if_backend uml
+skip_if_backend ()
+{
+    local b="$(guestfish get-backend)"
+    case "$1" in
+        # Some magic happens for $1 == libvirt.
+        libvirt)
+            if [ "$b" = "libvirt" ] || [[ "$b" =~ ^libvirt: ]]; then
+                echo "$(basename $0): test skipped because the current backend is $b"
+                exit 77
+            fi
+            ;;
+        *)
+            if [ "$b" = "$1" ]; then
+                echo "$(basename $0): test skipped because the current backend is $b"
+                exit 77
+            fi
+            ;;
+    esac
+}
+
+# Skip if the current libguestfs backend is NOT $1.
+skip_unless_backend ()
+{
+    local b="$(guestfish get-backend)"
+    case "$1" in
+        # Some magic happens for $1 == libvirt.
+        libvirt)
+            if [ "$b" != "libvirt" ] && [[ ! "$b" =~ ^libvirt: ]]; then
+                echo "$(basename $0): this test only runs if the backend is libvirt, but the current backend is $b"
+                exit 77
+            fi
+            ;;
+        *)
+            if [ "$b" != "$1" ]; then
+                echo "$(basename $0): this test only runs if the backend is $1, but the current backend is $b"
+                exit 77
+            fi
+            ;;
+    esac
+}
+
+# Skip if the named ($1) disk image in test-data/phony-guests was not
+# created.
+skip_unless_phony_guest ()
+{
+    local f="$abs_top_builddir/test-data/phony-guests/$1"
+    if ! test -f $f || ! test -s $f; then
+        echo "$(basename $0): test skipped because disk image '$1' was not created"
+        echo "$(basename $0): try running: make -C test-data check"
+        exit 77
+    fi
+}
+
+# Skip if test.iso was not created.
+skip_unless_test_iso ()
+{
+    local f="$abs_top_builddir/test-data/test.iso"
+    if ! test -f $f || ! test -s $f; then
+        echo "$(basename $0): test skipped because test-data/test.iso was not created"
+        echo "$(basename $0): try running: make -C test-data check"
+        exit 77
+    fi
+}
+
+# Skip if the current arch = $1.
+skip_if_arch ()
+{
+    local m="$(uname -m)"
+    case "$1" in
+        # Some magic happens for some architectures.
+        arm)
+            if [[ "$m" =~ ^arm ]]; then
+                echo "$(basename $0): test skipped because the current architecture ($m) is arm (32 bit)"
+                exit 77
+            fi
+            ;;
+        i?86)
+            if [[ "$m" =~ ^i?86 ]]; then
+                echo "$(basename $0): test skipped because the current architecture ($m) is $1"
+                exit 77
+            fi
+            ;;
+        *)
+            if [ "$m" = "$1" ]; then
+                echo "$(basename $0): test skipped because the current architecture ($m) is $1"
+                exit 77
+            fi
+            ;;
+    esac
+}
+
+# Skip if the current arch != $1.
+skip_unless_arch ()
+{
+    local m="$(uname -m)"
+    case "$1" in
+        # Some magic happens for some architectures.
+        arm)
+            if [[ ! "$m" =~ ^arm ]]; then
+                echo "$(basename $0): test skipped because the current architecture ($m) is not arm (32 bit)"
+                exit 77
+            fi
+            ;;
+        i?86)
+            if [[ ! "$m" =~ ^i?86 ]]; then
+                echo "$(basename $0): test skipped because the current architecture ($m) is not $1"
+                exit 77
+            fi
+            ;;
+        *)
+            if [ "$m" != "$1" ]; then
+                echo "$(basename $0): test skipped because the current architecture ($m) is not $1"
+                exit 77
+            fi
+            ;;
+    esac
+}
+
+# Skip if $1 is not known to virt-builder.
+skip_unless_virt_builder_guest ()
+{
+    if ! virt-builder -l "$1" >/dev/null 2>&1; then
+        echo "$(basename $0): test skipped because $1 is not known to virt-builder"
+        exit 77
+    fi
+}
+
+# Skip if FUSE is not available in the host kernel.
+skip_unless_fuse ()
+{
+    if ! test -w /dev/fuse; then
+        echo "$(basename $0): test skipped because the host kernel does not support FUSE"
+        echo "$(basename $0): /dev/fuse is missing or not writable by the current user"
+        exit 77
+    fi
+}
+
+# Skip if a feature is not available in the daemon.
+skip_unless_feature_available ()
+{
+    if ! guestfish -a /dev/null run : available "$1"; then
+        echo "$(basename $0): test skipped because feature $1 is not available"
+        exit 77
+    fi
+}
+
+# Skip unless the libvirt minimum version is met.
+skip_unless_libvirt_minimum_version ()
+{
+    if ! test -x $abs_top_builddir/lib/libvirt-is-version; then
+        echo "$(basename $0): test skipped because lib/libvirt-is-version is not built yet"
+        exit 77
+    fi
+    if ! $abs_top_builddir/lib/libvirt-is-version "$@"; then
+        echo "$(basename $0): test skipped because libvirt is too old, <" "$@"
+        exit 77
+    fi
+}
+
+# Run an external command and skip if the command fails.  This can be
+# used to test if a command exists.  Normally you should use
+# `cmd --help' or `cmd --version' or similar.
+skip_unless ()
+{
+    if ! "$@"; then
+        echo "$(basename $0): test skipped because $1 is not available"
+        exit 77
+    fi
+}
+
+# Skip if the user is trying to run a test as root.
+# Tests shouldn't be run as root, but a few are especially dangerous.
+skip_if_root ()
+{
+    if [ "$(id -u)" -eq 0 ]; then
+        echo "$(basename $0): test skipped because you're running tests as root."
+        echo "$(basename $0): it is NEVER a good idea to run libguestfs tests as root."
+    exit 77
+fi
+}
+
+# Slow tests should always call this function.  (See guestfs-hacking(1)).
+slow_test ()
+{
+    if [ -z "$SLOW" ]; then
+        echo "$(basename $0): use 'make check-slow' to run this test"
+        exit 77
+    fi
+}
+
 do_md5 ()
 {
   case "$(uname)" in
@@ -23,7 +249,7 @@ do_md5 ()
       md5sum "$1" | awk '{print $1}'
       ;;
     *)
-      echo "$0: unknown method to calculate MD5 of file on $(uname)"
+      echo "$(basename $0): unknown method to calculate MD5 of file on $(uname)"
       exit 1
       ;;
   esac
@@ -36,7 +262,7 @@ do_sha1 ()
       sha1sum "$1" | awk '{print $1}'
       ;;
     *)
-      echo "$0: unknown method to calculate SHA1 of file on $(uname)"
+      echo "$(basename $0): unknown method to calculate SHA1 of file on $(uname)"
       exit 1
       ;;
   esac
@@ -49,7 +275,7 @@ do_sha256 ()
       sha256sum "$1" | awk '{print $1}'
       ;;
     *)
-      echo "$0: unknown method to calculate SHA256 of file on $(uname)"
+      echo "$(basename $0): unknown method to calculate SHA256 of file on $(uname)"
       exit 1
       ;;
   esac
diff --git a/tests/tsk/test-download-blocks.sh b/tests/tsk/test-download-blocks.sh
index 234b557..862e126 100755
--- a/tests/tsk/test-download-blocks.sh
+++ b/tests/tsk/test-download-blocks.sh
@@ -20,26 +20,15 @@
 
 set -e
 
-if [ -n "$SKIP_TEST_DOWNLOAD_BLOCKS_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_feature_available sleuthkit
+skip_unless_phony_guest blank-fs.img
 
 rm -f test-download-blocks.bin
 
-# Skip if TSK is not supported by the appliance.
-if ! guestfish add /dev/null : run : available "sleuthkit"; then
-    echo "$0: skipped because TSK is not available in the appliance"
-    exit 77
-fi
-
-if [ ! -s ../../test-data/phony-guests/blank-fs.img ]; then
-    echo "$0: skipped because blank-fs.img is zero-sized"
-    exit 77
-fi
-
-# download Master File Table ($MFT).
-guestfish --ro -a ../../test-data/phony-guests/blank-fs.img <<EOF
+# Download Master File Table ($MFT).
+guestfish --ro -a $top_builddir/test-data/phony-guests/blank-fs.img <<EOF
 run
 mount /dev/sda1 /
 write /test.txt "$foo$bar$"
diff --git a/tests/tsk/test-download-inode.sh b/tests/tsk/test-download-inode.sh
index f57e424..905036c 100755
--- a/tests/tsk/test-download-inode.sh
+++ b/tests/tsk/test-download-inode.sh
@@ -20,26 +20,16 @@
 
 set -e
 
-if [ -n "$SKIP_TEST_DOWNLOAD_INODE_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_feature_available sleuthkit
+skip_unless_phony_guest windows.img
 
 rm -f test-mft.bin
 
-# Skip if TSK is not supported by the appliance.
-if ! guestfish add /dev/null : run : available "sleuthkit"; then
-    echo "$0: skipped because TSK is not available in the appliance"
-    exit 77
-fi
-
-if [ ! -s ../../test-data/phony-guests/windows.img ]; then
-    echo "$0: skipped because windows.img is zero-sized"
-    exit 77
-fi
-
-# download Master File Table ($MFT).
-guestfish --ro --format=raw -a ../../test-data/phony-guests/windows.img <<EOF
+# Download Master File Table ($MFT).
+guestfish \
+    --ro --format=raw -a $top_builddir/test-data/phony-guests/windows.img <<EOF
 run
 download-inode /dev/sda2 0 test-mft.bin
 EOF
diff --git a/tests/tsk/test-filesystem-walk.sh b/tests/tsk/test-filesystem-walk.sh
index f0c2d3d..c7f1efb 100755
--- a/tests/tsk/test-filesystem-walk.sh
+++ b/tests/tsk/test-filesystem-walk.sh
@@ -18,24 +18,13 @@
 
 # Test the filesystem-walk command.
 
-if [ -n "$SKIP_TEST_FILESYSTEM_WALK_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
-
-# Skip if TSK is not supported by the appliance.
-if ! guestfish add /dev/null : run : available "libtsk"; then
-    echo "$0: skipped because TSK is not available in the appliance"
-    exit 77
-fi
-
-if [ ! -s ../../test-data/phony-guests/windows.img ]; then
-    echo "$0: skipped because windows.img is zero-sized"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_feature_available libtsk
+skip_unless_phony_guest windows.img
 
 output=$(
-guestfish --ro -a ../../test-data/phony-guests/windows.img <<EOF
+guestfish --ro -a $top_builddir/test-data/phony-guests/windows.img <<EOF
 run
 mount /dev/sda2 /
 write /test.txt "foobar"
diff --git a/tests/tsk/test-find-inode.sh b/tests/tsk/test-find-inode.sh
index f69fcf6..cba282e 100755
--- a/tests/tsk/test-find-inode.sh
+++ b/tests/tsk/test-find-inode.sh
@@ -18,24 +18,13 @@
 
 # Test the find-inode command.
 
-if [ -n "$SKIP_TEST_FIND_INODE_SH" ]; then
-    echo "$0: test skipped because environment variable is set."
-    exit 77
-fi
-
-# Skip if TSK is not supported by the appliance.
-if ! guestfish add /dev/null : run : available "libtsk"; then
-    echo "$0: skipped because TSK is not available in the appliance"
-    exit 77
-fi
-
-if [ ! -s ../../test-data/phony-guests/windows.img ]; then
-    echo "$0: skipped because windows.img is zero-sized"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_feature_available libtsk
+skip_unless_phony_guest windows.img
 
 output=$(
-guestfish --ro -a ../../test-data/phony-guests/windows.img <<EOF
+guestfish --ro -a $top_builddir/test-data/phony-guests/windows.img <<EOF
 run
 find-inode /dev/sda2 0
 EOF
diff --git a/tools/test-virt-list-filesystems.sh b/tools/test-virt-list-filesystems.sh
index c4b003b..aa541df 100755
--- a/tools/test-virt-list-filesystems.sh
+++ b/tools/test-virt-list-filesystems.sh
@@ -16,12 +16,17 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_phony_guest fedora.img
+
 # Run virt-list-filesystems.
 # Only columns 1 & 2 are guaranteed, we may add more in future.
-if [ "$($srcdir/virt-list-filesystems --format=raw -l ../test-data/phony-guests/fedora.img |
+if [ "$($srcdir/virt-list-filesystems \
+            --format=raw -l \
+            $top_builddir/test-data/phony-guests/fedora.img |
         sort | awk '{print $1 $2}')" \
     != \
 "/dev/VG/LV1ext2
diff --git a/tools/test-virt-tar.sh b/tools/test-virt-tar.sh
index c4b8688..ef5fc0c 100755
--- a/tools/test-virt-tar.sh
+++ b/tools/test-virt-tar.sh
@@ -16,11 +16,16 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_phony_guest fedora.img
+
 # Read out the test directory using virt-tar.
-$srcdir/virt-tar -x ../test-data/phony-guests/fedora.img /bin test.tar
+$srcdir/virt-tar -x \
+                 $top_builddir/test-data/phony-guests/fedora.img /bin \
+                 test.tar
 
 if [ "$(tar tf test.tar | sort)" != "./
 ./ls
diff --git a/v2v/test-v2v-bad-networks-and-bridges.sh b/v2v/test-v2v-bad-networks-and-bridges.sh
index f336620..28d457a 100755
--- a/v2v/test-v2v-bad-networks-and-bridges.sh
+++ b/v2v/test-v2v-bad-networks-and-bridges.sh
@@ -18,17 +18,13 @@
 
 # Test detection of duplicate --network and --bridge parameters.
 
-unset CDPATH
-export LANG=C
 set -e
 set -x
 
-if [ -n "$SKIP_TEST_V2V_BAD_NETWORKS_AND_BRIDGES_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
 
-# We expect all of these to print an error.  NB LANG=C above.
+# We expect all of these to print an error.  NB: LANG=C is set.
 
 virt-v2v -i disk -b b1 -b b1 |& grep "duplicate -b"
 virt-v2v -i disk -n n1 -n n1 |& grep "duplicate -n"
diff --git a/v2v/test-v2v-cdrom.sh b/v2v/test-v2v-cdrom.sh
index 0679923..0c8680d 100755
--- a/v2v/test-v2v-cdrom.sh
+++ b/v2v/test-v2v-cdrom.sh
@@ -19,37 +19,17 @@
 # Test cdrom dev assignment.
 # https://bugzilla.redhat.com/show_bug.cgi?id=1238053
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_V2V_CDROM_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
-
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
+skip_unless_phony_guest windows.img
+skip_unless_phony_guest blank-disk.img
 
-abs_builddir="$(pwd)"
 libvirt_uri="test://$abs_builddir/test-v2v-cdrom.xml"
-
-f=../test-data/phony-guests/windows.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
-
-f=../test-data/phony-guests/blank-disk.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because blank-disk.img was not created"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
-export VIRTIO_WIN="$srcdir/../test-data/fake-virtio-win"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
+export VIRTIO_WIN="$top_srcdir/test-data/fake-virtio-win"
 
 d=test-v2v-cdrom.d
 rm -rf $d
diff --git a/v2v/test-v2v-conversion-of.sh b/v2v/test-v2v-conversion-of.sh
index a590085..4e98aaa 100755
--- a/v2v/test-v2v-conversion-of.sh
+++ b/v2v/test-v2v-conversion-of.sh
@@ -18,19 +18,12 @@
 
 # Test virt-v2v on real guests.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -z "$SLOW" ]; then
-    echo "$script: use 'make check-slow' to run this test"
-    exit 77
-fi
-
-if [ -n "$SKIP_TEST_V2V_CONVERSION_OF_SH" ]; then
-    echo "$script: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+slow_test
+skip_if_skipped "$script"
+skip_unless_arch x86_64
 
 guestname="$1"
 if [ -z "$guestname" ]; then
@@ -52,12 +45,6 @@ if ! virt-builder -l "$guestname" >/dev/null 2>&1; then
     exit 77
 fi
 
-# We can only run the tests on x86_64.
-if [ "$(uname -m)" != "x86_64" ]; then
-    echo "$script: test skipped because !x86_64."
-    exit 77
-fi
-
 # Some guests need special virt-builder parameters.
 # See virt-builder --notes "$guestname"
 declare -a extra
diff --git a/v2v/test-v2v-copy-to-local.sh b/v2v/test-v2v-copy-to-local.sh
index 8629083..3eb384a 100755
--- a/v2v/test-v2v-copy-to-local.sh
+++ b/v2v/test-v2v-copy-to-local.sh
@@ -18,24 +18,14 @@
 
 # Test virt-v2v-copy-to-local command.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_V2V_COPY_TO_LOCAL_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_phony_guest fedora.img
 
-abs_top_builddir="$(cd ..; pwd)"
 libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml"
 
-f=../test-data/phony-guests/fedora.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because phony Fedora image was not created"
-    exit 77
-fi
-
 d=test-v2v-copy-to-local.d
 rm -rf $d
 mkdir $d
diff --git a/v2v/test-v2v-docs.sh b/v2v/test-v2v-docs.sh
index a88c10c..d341852 100755
--- a/v2v/test-v2v-docs.sh
+++ b/v2v/test-v2v-docs.sh
@@ -16,8 +16,10 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-export LANG=C
 set -e
 
-$srcdir/../podcheck.pl virt-v2v.pod virt-v2v \
+$TEST_FUNCTIONS
+skip_if_skipped
+
+$top_srcdir/podcheck.pl virt-v2v.pod virt-v2v \
   --ignore=--dcPath,--debug-overlay,--ic,--if,--no-trim,--oa,--oc,--of,--on,--os,--vmtype
diff --git a/v2v/test-v2v-floppy.sh b/v2v/test-v2v-floppy.sh
index 1f3f1bc..ac407b4 100755
--- a/v2v/test-v2v-floppy.sh
+++ b/v2v/test-v2v-floppy.sh
@@ -19,37 +19,18 @@
 # Test converting a guest with a floppy disk.
 # https://bugzilla.redhat.com/show_bug.cgi?id=1309706
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_V2V_FLOPPY_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
-
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
+skip_unless_phony_guest windows.img
+skip_unless_phony_guest blank-disk.img
 
-abs_builddir="$(pwd)"
 libvirt_uri="test://$abs_builddir/test-v2v-floppy.xml"
 
-f=../test-data/phony-guests/windows.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
-
-f=../test-data/phony-guests/blank-disk.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because blank-disk.img was not created"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
-export VIRTIO_WIN="$srcdir/../test-data/fake-virtio-win"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
+export VIRTIO_WIN="$top_srcdir/test-data/fake-virtio-win"
 
 d=test-v2v-floppy.d
 rm -rf $d
diff --git a/v2v/test-v2v-i-disk.sh b/v2v/test-v2v-i-disk.sh
index b806a44..c4b519c 100755
--- a/v2v/test-v2v-i-disk.sh
+++ b/v2v/test-v2v-i-disk.sh
@@ -18,34 +18,21 @@
 
 # Test -i disk option.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_V2V_I_DISK_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
+skip_unless_phony_guest windows.img
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
-
-f=../test-data/phony-guests/windows.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
 
 d=test-v2v-i-disk.d
 rm -rf $d
 mkdir $d
 
 $VG virt-v2v --debug-gc \
-    -i disk $f \
+    -i disk $top_builddir/test-data/phony-guests/windows.img \
     -o local -os $d
 
 # Test the libvirt XML metadata and a disk was created.
diff --git a/v2v/test-v2v-i-ova-formats.sh b/v2v/test-v2v-i-ova-formats.sh
index d49b7be..d357287 100755
--- a/v2v/test-v2v-i-ova-formats.sh
+++ b/v2v/test-v2v-i-ova-formats.sh
@@ -18,35 +18,17 @@
 
 # Test -i ova option with ova file compressed in different ways
 
-unset CDPATH
-export LANG=C
 set -e
 
 $TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
+skip_unless zip --version
+skip_unless unzip --help
 
 formats="zip tar-gz tar-xz"
 
-if [ -n "$SKIP_TEST_V2V_I_OVA_FORMATS_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
-
-if ! zip --version >/dev/null 2>&1; then
-    echo "$0: test skipped because 'zip' utility is not available"
-    exit 77
-fi
-
-if ! unzip --help >/dev/null 2>&1; then
-    echo "$0: test skipped because 'unzip' utility is not available"
-    exit 77
-fi
-
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
 
 d=test-v2v-i-ova-formats.d
 rm -rf $d
diff --git a/v2v/test-v2v-i-ova-gz.sh b/v2v/test-v2v-i-ova-gz.sh
index e292683..2bf2f5e 100755
--- a/v2v/test-v2v-i-ova-gz.sh
+++ b/v2v/test-v2v-i-ova-gz.sh
@@ -23,18 +23,10 @@ export LANG=C
 set -e
 
 $TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
 
-if [ -n "$SKIP_TEST_V2V_I_OVA_GZ_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
-
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
 
 d=test-v2v-i-ova-gz.d
 rm -rf $d
diff --git a/v2v/test-v2v-i-ova-subfolders.sh b/v2v/test-v2v-i-ova-subfolders.sh
index ea3352c..12e0e87 100755
--- a/v2v/test-v2v-i-ova-subfolders.sh
+++ b/v2v/test-v2v-i-ova-subfolders.sh
@@ -23,18 +23,10 @@ export LANG=C
 set -e
 
 $TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
 
-if [ -n "$SKIP_TEST_V2V_I_OVA_SUBFOLDERS_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
-
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
 
 d=test-v2v-i-ova-subfolders.d
 rm -rf $d
diff --git a/v2v/test-v2v-i-ova-tar.sh b/v2v/test-v2v-i-ova-tar.sh
index 2d1389d..003d5e6 100755
--- a/v2v/test-v2v-i-ova-tar.sh
+++ b/v2v/test-v2v-i-ova-tar.sh
@@ -23,18 +23,10 @@ export LANG=C
 set -e
 
 $TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
 
-if [ -n "$SKIP_TEST_V2V_I_OVA_FORMATS_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
-
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
 
 d=test-v2v-i-ova-tar.d
 rm -rf $d
diff --git a/v2v/test-v2v-i-ova-two-disks.sh b/v2v/test-v2v-i-ova-two-disks.sh
index 86584c3..9ecc380 100755
--- a/v2v/test-v2v-i-ova-two-disks.sh
+++ b/v2v/test-v2v-i-ova-two-disks.sh
@@ -23,19 +23,11 @@ export LANG=C
 set -e
 
 $TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
 
-if [ -n "$SKIP_TEST_V2V_I_OVA_TWO_DISKS_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
-
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
-export VIRTIO_WIN="$srcdir/../test-data/fake-virtio-win"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
+export VIRTIO_WIN="$top_srcdir/test-data/fake-virtio-win"
 
 d=test-v2v-i-ova-two-disks.d
 rm -rf $d
diff --git a/v2v/test-v2v-i-ova.sh b/v2v/test-v2v-i-ova.sh
index 4b97a1a..7a33b6c 100755
--- a/v2v/test-v2v-i-ova.sh
+++ b/v2v/test-v2v-i-ova.sh
@@ -18,37 +18,19 @@
 
 # Test -i ova option.
 
-unset CDPATH
-export LANG=C
 set -e
 
 $TEST_FUNCTIONS
-
-if [ -n "$SKIP_TEST_V2V_I_OVA_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
-
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
+skip_if_skipped
+skip_if_backend uml
+skip_unless_phony_guest windows.img
 
 # XXX Remove when we fix this.  See:
 # https://www.redhat.com/archives/libguestfs/2017-February/msg00101.html
-if [[ "$(guestfish get-backend)" =~ ^libvirt ]]; then
-    echo "$0: test skipped because of bug with virt-v2v -i ova and libvirt"
-    exit 77
-fi
-
-f=../test-data/phony-guests/windows.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
+skip_if_backend libvirt
 
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
-export VIRTIO_WIN="$srcdir/../test-data/fake-virtio-win"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
+export VIRTIO_WIN="$top_srcdir/test-data/fake-virtio-win"
 
 d=test-v2v-i-ova.d
 rm -rf $d
@@ -60,7 +42,8 @@ mf=test-ova.mf
 ova=test-ova.ova
 raw=TestOva-sda
 
-qemu-img convert $f -O vmdk $d/$vmdk
+qemu-img convert $top_builddir/test-data/phony-guests/windows.img \
+         -O vmdk $d/$vmdk
 cp $ovf $d/$ovf
 sha1=`do_sha1 $d/$ovf`
 echo "SHA1($ovf)= $sha1" > $d/$mf
diff --git a/v2v/test-v2v-in-place.sh b/v2v/test-v2v-in-place.sh
index c8b2ec4..6f7d78f 100755
--- a/v2v/test-v2v-in-place.sh
+++ b/v2v/test-v2v-in-place.sh
@@ -24,27 +24,14 @@ export LANG=C
 set -e
 
 $TEST_FUNCTIONS
-
-if [ -n "$SKIP_TEST_V2V_IN_PLACE_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
-
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
-
-abs_top_builddir="$(cd ..; pwd)"
+skip_if_skipped
+skip_if_backend uml
+skip_unless_phony_guest windows.img
 
 img_base="$abs_top_builddir/test-data/phony-guests/windows.img"
-if ! test -f $img_base || ! test -s $img_base; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
 
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
-export VIRTIO_WIN="$srcdir/../test-data/fake-virtio-win"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
+export VIRTIO_WIN="$top_srcdir/test-data/fake-virtio-win"
 
 d=$PWD/test-v2v-in-place.d
 rm -rf $d
diff --git a/v2v/test-v2v-machine-readable.sh b/v2v/test-v2v-machine-readable.sh
index 3e94ae5..1402b30 100755
--- a/v2v/test-v2v-machine-readable.sh
+++ b/v2v/test-v2v-machine-readable.sh
@@ -18,14 +18,10 @@
 
 # Test --machine-readable option.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_V2V_MACHINE_READABLE_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
 
 $VG virt-v2v --debug-gc --machine-readable > test-v2v-machine-readable.out
 grep virt-v2v test-v2v-machine-readable.out
diff --git a/v2v/test-v2v-networks-and-bridges.sh b/v2v/test-v2v-networks-and-bridges.sh
index 5b3d6e0..5a2e645 100755
--- a/v2v/test-v2v-networks-and-bridges.sh
+++ b/v2v/test-v2v-networks-and-bridges.sh
@@ -18,30 +18,17 @@
 
 # Test --network and --bridge parameters.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_V2V_NETWORKS_AND_BRIDGES_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
+skip_unless_phony_guest windows.img
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
-
-abs_builddir="$(pwd)"
 libvirt_uri="test://$abs_builddir/test-v2v-networks-and-bridges.xml"
+f=$top_builddir/test-data/phony-guests/windows.img
 
-f=../test-data/phony-guests/windows.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
 
 d=test-v2v-networks-and-bridges.d
 rm -rf $d
diff --git a/v2v/test-v2v-no-copy.sh b/v2v/test-v2v-no-copy.sh
index 23109ae..6eacd0d 100755
--- a/v2v/test-v2v-no-copy.sh
+++ b/v2v/test-v2v-no-copy.sh
@@ -18,30 +18,17 @@
 
 # Test --no-copy option.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_V2V_NO_COPY_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
+skip_unless_phony_guest windows.img
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
-
-abs_top_builddir="$(cd ..; pwd)"
 libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml"
+f=$top_builddir/test-data/phony-guests/windows.img
 
-f=../test-data/phony-guests/windows.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
 
 d=test-v2v-no-copy.d
 rm -rf $d
diff --git a/v2v/test-v2v-o-glance.sh b/v2v/test-v2v-o-glance.sh
index 7620365..94985cc 100755
--- a/v2v/test-v2v-o-glance.sh
+++ b/v2v/test-v2v-o-glance.sh
@@ -18,30 +18,17 @@
 
 # Test -o glance.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_V2V_O_GLANCE_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
+skip_unless_phony_guest windows.img
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
-
-abs_top_builddir="$(cd ..; pwd)"
 libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml"
+f=$top_builddir/test-data/phony-guests/windows.img
 
-f=../test-data/phony-guests/windows.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
 
 # We don't want to upload to the real glance, so introduce a fake
 # glance binary.
diff --git a/v2v/test-v2v-o-libvirt.sh b/v2v/test-v2v-o-libvirt.sh
index f2941e9..0234ef7 100755
--- a/v2v/test-v2v-o-libvirt.sh
+++ b/v2v/test-v2v-o-libvirt.sh
@@ -18,47 +18,28 @@
 
 # Test -o libvirt.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_V2V_O_LIBVIRT_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
-
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
+skip_unless_phony_guest fedora.img
 
 # You shouldn't be running the tests as root anyway, but in this case
 # it's especially bad because we don't want to start creating guests
 # or storage pools in the system namespace.
-if [ "$(id -u)" -eq 0 ]; then
-    echo "$0: test skipped because you're running tests as root.  Don't do that!"
-    exit 77
-fi
+skip_if_root
 
 # Since libvirt ~ 1.2.19, it started to check that the guest
 # architecture was valid at guest creation time, rather than when you
 # first run the guest.  Since the guest XML contains arch='x86_64',
 # this test will fail on !x86_64.
-if [ "$(uname -m)" != "x86_64" ]; then
-    echo "$0: test skipped because !x86_64"
-    exit 77
-fi
+skip_unless_arch x86_64
 
-abs_top_builddir="$(cd ..; pwd)"
 libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml"
+f=$top_builddir/test-data/phony-guests/windows.img
 
-f=../test-data/phony-guests/windows.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
 
 # Generate a random guest name.
 guestname=tmp-$(tr -cd 'a-f0-9' < /dev/urandom | head -c 8)
diff --git a/v2v/test-v2v-o-null.sh b/v2v/test-v2v-o-null.sh
index 657cd53..3310961 100755
--- a/v2v/test-v2v-o-null.sh
+++ b/v2v/test-v2v-o-null.sh
@@ -18,30 +18,17 @@
 
 # Test -o null.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_V2V_O_NULL_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
+skip_unless_phony_guest windows.img
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
-
-abs_top_builddir="$(cd ..; pwd)"
 libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml"
+f=$top_builddir/test-data/phony-guests/windows.img
 
-f=../test-data/phony-guests/windows.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
 
 $VG virt-v2v --debug-gc \
     -i libvirt -ic "$libvirt_uri" windows \
diff --git a/v2v/test-v2v-o-qemu.sh b/v2v/test-v2v-o-qemu.sh
index 3a5618d..7f2aba5 100755
--- a/v2v/test-v2v-o-qemu.sh
+++ b/v2v/test-v2v-o-qemu.sh
@@ -18,30 +18,17 @@
 
 # Test -o qemu.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_V2V_O_QEMU_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
+skip_unless_phony_guest windows.img
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
-
-abs_top_builddir="$(cd ..; pwd)"
 libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml"
+f=$top_builddir/test-data/phony-guests/windows.img
 
-f=../test-data/phony-guests/windows.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
 
 d=test-v2v-o-qemu.d
 rm -rf $d
diff --git a/v2v/test-v2v-o-rhv.sh b/v2v/test-v2v-o-rhv.sh
index ce43b27..413e013 100755
--- a/v2v/test-v2v-o-rhv.sh
+++ b/v2v/test-v2v-o-rhv.sh
@@ -18,30 +18,17 @@
 
 # Test -o rhv.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_V2V_O_RHV_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
+skip_unless_phony_guest windows.img
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
-
-abs_top_builddir="$(cd ..; pwd)"
 libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml"
+f=$top_builddir/test-data/phony-guests/windows.img
 
-f=../test-data/phony-guests/windows.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
 
 d=test-v2v-o-rhv.d
 rm -rf $d
diff --git a/v2v/test-v2v-o-vdsm-options.sh b/v2v/test-v2v-o-vdsm-options.sh
index bb366d7..4352738 100755
--- a/v2v/test-v2v-o-vdsm-options.sh
+++ b/v2v/test-v2v-o-vdsm-options.sh
@@ -18,31 +18,18 @@
 
 # Test -o vdsm options --vdsm-*-uuid
 
-unset CDPATH
-export LANG=C
 set -e
 set -x
 
-if [ -n "$SKIP_TEST_V2V_O_VDSM_OPTIONS_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
+skip_unless_phony_guest windows.img
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
-
-abs_top_builddir="$(cd ..; pwd)"
 libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml"
+f=$top_builddir/test-data/phony-guests/windows.img
 
-f=../test-data/phony-guests/windows.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
 
 d=test-v2v-o-vdsm-options.d
 rm -rf $d
diff --git a/v2v/test-v2v-oa-option.sh b/v2v/test-v2v-oa-option.sh
index be65de7..2a0d4dd 100755
--- a/v2v/test-v2v-oa-option.sh
+++ b/v2v/test-v2v-oa-option.sh
@@ -18,30 +18,18 @@
 
 # Test virt-v2v -oa (sparse/preallocated) option.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_V2V_OA_OPTION_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
-
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network or qcow2"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+# No support for either network or qcow2.
+skip_if_backend uml
+skip_unless_phony_guest windows.img
 
-abs_top_builddir="$(cd ..; pwd)"
 libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml"
+f=$top_builddir/test-data/phony-guests/windows.img
 
-f=../test-data/phony-guests/windows.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
 
 d=test-v2v-oa-option.d
 rm -rf $d
diff --git a/v2v/test-v2v-of-option.sh b/v2v/test-v2v-of-option.sh
index 3a0525f..145e9b8 100755
--- a/v2v/test-v2v-of-option.sh
+++ b/v2v/test-v2v-of-option.sh
@@ -18,30 +18,18 @@
 
 # Test virt-v2v -of (format conversion) option.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_V2V_OF_OPTION_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
-
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network or qcow2"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+# No support for either network or qcow2.
+skip_if_backend uml
+skip_unless_phony_guest windows.img
 
-abs_top_builddir="$(cd ..; pwd)"
 libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml"
+f=$top_builddir/test-data/phony-guests/windows.img
 
-f=../test-data/phony-guests/windows.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
 
 d=test-v2v-of-option.d
 rm -rf $d
diff --git a/v2v/test-v2v-on-option.sh b/v2v/test-v2v-on-option.sh
index 1816fb4..b30e8da 100755
--- a/v2v/test-v2v-on-option.sh
+++ b/v2v/test-v2v-on-option.sh
@@ -18,30 +18,17 @@
 
 # Test virt-v2v -on (change name) option.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_V2V_ON_OPTION_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
+skip_unless_phony_guest windows.img
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
-
-abs_top_builddir="$(cd ..; pwd)"
 libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml"
+f=$top_builddir/test-data/phony-guests/windows.img
 
-f=../test-data/phony-guests/windows.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
 
 d=test-v2v-on-option.d
 rm -rf $d
diff --git a/v2v/test-v2v-print-source.sh b/v2v/test-v2v-print-source.sh
index 789555d..62899e6 100755
--- a/v2v/test-v2v-print-source.sh
+++ b/v2v/test-v2v-print-source.sh
@@ -18,23 +18,14 @@
 
 # Test --print-source option.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_V2V_PRINT_SOURCE_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_phony_guest windows.img
 
-abs_top_builddir="$(cd ..; pwd)"
 libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml"
-
-f=../test-data/phony-guests/windows.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
+f=$top_builddir/test-data/phony-guests/windows.img
 
 d=test-v2v-print-source.d
 rm -rf $d
diff --git a/v2v/test-v2v-sound.sh b/v2v/test-v2v-sound.sh
index 594bfff..91f60cc 100755
--- a/v2v/test-v2v-sound.sh
+++ b/v2v/test-v2v-sound.sh
@@ -18,30 +18,17 @@
 
 # Test <sound> is transferred to destination domain.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_V2V_SOUND_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_unless_backend uml
+skip_unless_phony_guest windows.img
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
-
-abs_builddir="$(pwd)"
 libvirt_uri="test://$abs_builddir/test-v2v-sound.xml"
+f=$top_builddir/test-data/phony-guests/windows.img
 
-f=../test-data/phony-guests/windows.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
 
 d=test-v2v-sound.d
 rm -rf $d
diff --git a/v2v/test-v2v-trim.sh b/v2v/test-v2v-trim.sh
index 6b0eae8..67dc5f8 100755
--- a/v2v/test-v2v-trim.sh
+++ b/v2v/test-v2v-trim.sh
@@ -18,26 +18,16 @@
 
 # Test that trimming doesn't regress.  Suggested by Ming Xie in
 # https://bugzilla.redhat.com/show_bug.cgi?id=1264332
+#
+# Note: This test is expected to fail on NFS, we should automatically
+# skip in that case (XXX - how?).
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -z "$SLOW" ]; then
-    echo "$0: use 'make check-slow' to run this test"
-    exit 77
-fi
-
-# This test is expected to fail on NFS.
-if [ -n "$SKIP_TEST_V2V_TRIM_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
-
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: skipping test because uml backend does not support discard"
-    exit 77
-fi
+$TEST_FUNCTIONS
+slow_test
+skip_if_skipped
+skip_if_backend uml
 
 d=test-v2v-trim.d
 rm -rf $d
diff --git a/v2v/test-v2v-virtio-win-iso.sh b/v2v/test-v2v-virtio-win-iso.sh
index 49cda02..4f1a0f7 100755
--- a/v2v/test-v2v-virtio-win-iso.sh
+++ b/v2v/test-v2v-virtio-win-iso.sh
@@ -19,32 +19,18 @@
 
 # Test virt-v2v Windows conversion with VirtIO drivers on an ISO image.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_V2V_VIRTIO_WIN_ISO_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
-
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
+skip_unless_backend windows.img
 
-abs_top_builddir="$(cd ..; pwd)"
 libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml"
+f=$top_builddir/test-data/phony-guests/windows.img
 
-f=../test-data/phony-guests/windows.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
-# NB: This is located in the builddir:
-export VIRTIO_WIN="../test-data/fake-virtio-win/fake-virtio-win.iso"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
+export VIRTIO_WIN="$top_builddir/test-data/fake-virtio-win/fake-virtio-win.iso"
 
 if ! test -f "$VIRTIO_WIN"; then
     echo "$0: test skipped because fake virtio-win iso image was not created"
diff --git a/v2v/test-v2v-windows-conversion.sh b/v2v/test-v2v-windows-conversion.sh
index 5e745c7..4cc54f6 100755
--- a/v2v/test-v2v-windows-conversion.sh
+++ b/v2v/test-v2v-windows-conversion.sh
@@ -18,31 +18,18 @@
 
 # Test virt-v2v (Phony) Windows conversion.
 
-unset CDPATH
-export LANG=C
 set -e
 
-if [ -n "$SKIP_TEST_V2V_WINDOWS_CONVERSION_SH" ]; then
-    echo "$0: test skipped because environment variable is set"
-    exit 77
-fi
+$TEST_FUNCTIONS
+skip_if_skipped
+skip_if_backend uml
+skip_unless_backend windows.img
 
-if [ "$(guestfish get-backend)" = "uml" ]; then
-    echo "$0: test skipped because UML backend does not support network"
-    exit 77
-fi
-
-abs_top_builddir="$(cd ..; pwd)"
 libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml"
+f=$top_builddir/test-data/phony-guests/windows.img
 
-f=../test-data/phony-guests/windows.img
-if ! test -f $f || ! test -s $f; then
-    echo "$0: test skipped because phony Windows image was not created"
-    exit 77
-fi
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
-export VIRTIO_WIN="$srcdir/../test-data/fake-virtio-win"
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
+export VIRTIO_WIN="$top_srcdir/test-data/fake-virtio-win"
 
 # Return a random element from the array 'choices'.
 function random_choice
-- 
2.9.3




More information about the Libguestfs mailing list