diff --git a/example/test-example b/example/test-example
index 8705fe0f4b1960ce97ae65d93ed0612d622d3bb4..b6364e7033a56d3f4e5384e1be26fd52518f2e01 100755
--- a/example/test-example
+++ b/example/test-example
@@ -10,11 +10,30 @@ import re
 import datetime
 from textwrap import dedent
 
-def assert_pattern_matches_string(description, pattern, string):
-    if pattern is None: return
+def assert_stdout_err_ret(expected_stdout, stdout, expected_stderr, stderr, expected_returncode, returncode):
+    """ Verify stdout, stderr, and return code from a program.
+
+    We test all three at once, as all three are often useful in diagnosing
+    the problem if any of them is wrong.
+    """
+    if (re.search(expected_stdout, stdout) and
+        re.search(expected_stderr, stderr) and
+        expected_returncode == returncode
+            ):
+        return
+
+    msg = "Program did not return expected results.\n"
+    if expected_stdout is not None and not re.search(expected_stdout, stdout):
+        msg += f"Standard output does not match expectation.\nExpected regular repression:\n    {repr(expected_stdout)}\nActual:\n    {repr(stdout)}\n"
+    if expected_stderr is not None and not re.search(expected_stderr, stderr):
+        msg += f"Standard error does not match expectation.\nExpected regular repression:\n    {repr(expected_stderr)}\nActual:\n    {repr(stderr)}\n"
+    if expected_returncode != returncode:
+        msg += f"Return code should have been {expected_returncode} but is {returncode}.\n"
+    raise AssertionError(msg)
+
+
+
 
-    if not re.search(pattern, string):
-        raise AssertionError(f"{description} does not match expectation.\nExpected regular repression:\n{repr(pattern)}\nActual:\n{repr(string)}")
 
 class TestCase (csppfetch.test_extensions.TestCase):
     def assertDownloadCommand(self, cmd, web_files, expected_files, expected_stdout=None, expected_stderr=None, expected_returncode=0):
@@ -29,8 +48,9 @@ class TestCase (csppfetch.test_extensions.TestCase):
                         CSPP_GEO_AITF_ANCIL_CONNECT_TIMEOUT="0.1",
                         CSPP_GEO_AITF_ANCIL_RETRY_WAIT="0"):
                     ret = subprocess.run(cmd, capture_output=True, text=True)
-                    assert_pattern_matches_string("Standard error",  expected_stderr, ret.stderr)
-                    assert_pattern_matches_string("Standard output", expected_stdout, ret.stdout)
+                    assert_stdout_err_ret(expected_stdout, ret.stdout,
+                            expected_stderr, ret.stderr,
+                            expected_returncode, ret.returncode)
                     self.assertEqual(ret.returncode,expected_returncode)
                     self.assertDirectoryContents(outdir, expected_files)
 
@@ -81,8 +101,8 @@ class Test_aitf_data_for_run (TestCase):
                 "gfs_grib2_0.5deg/2023/02/09/gfs.t00z.pgrbf06": 'gfs.t00z.230209.pgrb2f06',
                 "oisst_daily/avhrr-only-v2.20230209_preliminary.nc": None
             },
-            expected_stdout = "",
-            expected_stderr = ""
+            expected_stdout = "^$",
+            expected_stderr = "^$"
             )
 
     def test_simple_case(self):
@@ -107,7 +127,7 @@ class Test_aitf_data_for_run (TestCase):
                 "oisst_daily/avhrr-only-v2.20230209_preliminary.nc": None
             },
             expected_stdout = data_for_run_output(SST_files=1, GFS_files=2),
-            expected_stderr = ""
+            expected_stderr = "^$"
             )
 
     def test_older_OISST(self):
@@ -132,7 +152,7 @@ class Test_aitf_data_for_run (TestCase):
                 "oisst_daily/avhrr-only-v2.20230208_preliminary.nc": None
             },
             expected_stdout = data_for_run_output(SST_files=1, GFS_files=2),
-            expected_stderr = ""
+            expected_stderr = "^$"
             )
 
     def test_older_GFS(self):
@@ -156,7 +176,7 @@ class Test_aitf_data_for_run (TestCase):
                 "oisst_daily/avhrr-only-v2.20230209_preliminary.nc": None
             },
             expected_stdout = data_for_run_output(SST_files=1, GFS_files=2),
-            expected_stderr = ""
+            expected_stderr = "^$"
             )
 
     def test_missing_GFS(self):
@@ -185,7 +205,7 @@ class Test_aitf_data_for_run (TestCase):
                 "oisst_daily/avhrr-only-v2.20230209_preliminary.nc": None
             },
             expected_stdout = expected_stdout,
-            expected_stderr = "",
+            expected_stderr = "^$",
             expected_returncode = 1,
             )
 
@@ -223,7 +243,7 @@ class Test_aitf_data_for_run (TestCase):
                 #"gfs_grib2_0.5deg/2023/02/09/gfs.t00z.pgrbf06": 'gfs.t00z.230209.pgrb2f06',
             },
             expected_stdout = expected_stdout,
-            expected_stderr = "",
+            expected_stderr = "^$",
             expected_returncode = 1,
             )
 
@@ -239,9 +259,9 @@ class Test_aitf_data_for_run (TestCase):
             "oisst_daily/avhrr-only-v2.20230209_preliminary.nc": None,
             }
         expected_stdout_1 = data_for_run_output(SST_files=1, GFS_files=2)
-        expected_stderr_1 = ""
+        expected_stderr_1 = "^$"
         expected_stdout_2 = data_for_run_output(SST_files=0, GFS_files=0, SST_cache_files=1, GFS_cache_files=2)
-        expected_stderr_2 = ""
+        expected_stderr_2 = "^$"
 
         with tempfile.TemporaryDirectory(prefix="csppfetch-test") as outdir:
             with PopulatedManagedWebserver(web_files) as url:
@@ -250,15 +270,15 @@ class Test_aitf_data_for_run (TestCase):
                         CSPP_GEO_AITF_ANCIL_RETRY_WAIT="1"):
                     cmd = ["./aitf-data-for-run", "-v", "--cache", outdir, "2023-02-09T03:00:00"]
                     ret = subprocess.run(cmd , capture_output=True, text=True)
-                    assert_pattern_matches_string("Standard error",  expected_stderr_1, ret.stderr)
-                    assert_pattern_matches_string("Standard output", expected_stdout_1, ret.stdout)
-                    self.assertEqual(ret.returncode,0)
+                    assert_stdout_err_ret(expected_stdout_1, ret.stdout,
+                            expected_stderr_1, ret.stderr,
+                            0, ret.returncode)
                     self.assertDirectoryContents(outdir, expected_files)
 
                     ret = subprocess.run(cmd , capture_output=True, text=True)
-                    assert_pattern_matches_string("Standard error",  expected_stderr_2, ret.stderr)
-                    assert_pattern_matches_string("Standard output", expected_stdout_2, ret.stdout)
-                    self.assertEqual(ret.returncode,0)
+                    assert_stdout_err_ret(expected_stdout_2, ret.stdout,
+                            expected_stderr_2, ret.stderr,
+                            0, ret.returncode)
                     self.assertDirectoryContents(outdir, expected_files)
 
 class Test_aitf_update_cache (TestCase):
@@ -320,8 +340,8 @@ class Test_aitf_update_cache (TestCase):
             ["./aitf-update-cache", "--newest", "2023-02-15", "CACHEDIR"],
             web_files=web_files,
             expected_files=expected_files,
-            expected_stdout="",
-            expected_stderr="",
+            expected_stdout="^$",
+            expected_stderr="^$",
             )
 
     @unittest.skip("not yet implemented")
@@ -355,8 +375,8 @@ class Test_aitf_update_cache (TestCase):
                 ["./aitf-update-cache", "--newest", "2023-02-09T13:20:00", "--oldest", "2023-02-09T13:10:00", "CACHEDIR"],
                 web_files=web_files,
                 expected_files=expected_files,
-                expected_stdout="",
-                expected_stderr="",
+                expected_stdout="^$",
+                expected_stderr="^$",
                 )