diff --git a/TODO.md b/TODO.md
index 9ee9ffd..48e1fb4 100644
--- a/TODO.md
+++ b/TODO.md
@@ -6,4 +6,19 @@
 - Spike: resolving multiple references to the same dependency
   - ie. two files which both #load the same file
   - Reason: If we can resolve this, it would enable compiling tests as a single compilation unit
-    rather than multiple, which will significantly speed up test compilation
\ No newline at end of file
+    rather than multiple, which will significantly speed up test compilation
+
+- check for Test declarations after Run_Test_Harness
+  - maybe insert an end_of_main function that looks for
+    declarations that didn't run?
+
+- investigate multi-file tests.
+  - what happens if you do something like:
+    ```
+    #load "tests_a.jai";
+    main :: () {
+      Init_Test_Harness();
+      tests_declared_in_test_a();
+      Run_Test_Harness();
+    }
+    ```
\ No newline at end of file
diff --git a/module.jai b/module.jai
index 6990788..7384cde 100644
--- a/module.jai
+++ b/module.jai
@@ -140,9 +140,21 @@ output :: ()
     print_to_builder(*run_all_tests_builder, "\n# Category: %\n", category.category_name);
     if category.category_name != "default"
     {
-      print_to_builder(*run_all_tests_builder, "if [[ \" ${ARGS[*]} \" =~ \" % \" ]]; then\n", category.category_name);
+      RUN_CONDITION :: "if [[ \" ${ARGS[*]} \" =~ \" % \" ]] || [[ \" ${ARGS[*]} \" =~ \" all \" ]]; then\n";
+      print_to_builder(*run_all_tests_builder, RUN_CONDITION, category.category_name);
     }
-    print_to_builder(*run_all_tests_builder, "%\n", builder_to_string(category_builder));
+
+    category_tests_string := builder_to_string(category_builder);
+    if category_tests_string.count > 0 {
+      print_to_builder(*run_all_tests_builder, "%\n", category_tests_string);
+    } else {
+      print_to_builder(
+        *run_all_tests_builder,
+        "echo No tests in this category: %\n",
+        category.category_name
+      );
+    }
+
     if category.category_name != "default"
     {
       print_to_builder(*run_all_tests_builder, "fi\n");
diff --git a/tests/basic.manual_test.jai b/tests/basic.manual_test.jai
new file mode 100644
index 0000000..7f74b6c
--- /dev/null
+++ b/tests/basic.manual_test.jai
@@ -0,0 +1,5 @@
+// See ./basic_build.jai for an explanation
+
+main :: () {
+  print("This is a manual test!\n");
+}
\ No newline at end of file
diff --git a/tests/basic_build.jai b/tests/basic_build.jai
index 1cee36c..f8b130d 100644
--- a/tests/basic_build.jai
+++ b/tests/basic_build.jai
@@ -17,6 +17,33 @@ build :: ()
     test_categories = .[
       .{
         file_extension = ".gs_test.jai",
+      },
+      .{
+        file_extension = ".test_group_b.jai",
+
+        category_name = "group_b",
+        // It's useful to be able to run only a subset of your total
+        // test suite. By creating categories, you can specifiy
+        // individual categories to run in run_all_tests.sh
+      },
+
+      // Sometimes it's useful to have a set of files get compiled
+      // along side your tests but which you don't want run with
+      // the automated test suite - for example, tests that rely
+      // on creating windows, etc.
+      .{
+        file_extension = ".manual_test.jai",
+
+        exe_extension = ".manual.test",
+        // exe_extension will get appended to the output filename
+        // before any platform specific executable extensions.
+        // ie. on windows this will output basic.manual.test.exe
+
+        category_name = "manual",
+
+        exclude_from_run_all_tests = true,
+        // all output executables in this category will be omitted
+        // from run_all_tests.sh
       }
     ]
   }, target_options);
diff --git a/tests/basic_usage.gs_test.jai b/tests/basic_usage.gs_test.jai
index f66d1cc..4676203 100644
--- a/tests/basic_usage.gs_test.jai
+++ b/tests/basic_usage.gs_test.jai
@@ -1,12 +1,42 @@
+// This is a basic example test.
+
 #load "./example_math.jai";
+// You can import files and libraries as normal.
+//
+// Note you do not have to import anything for the test
+// suite specifically. That gets handled by the metaprogram.
 
 main :: () {
-  Init_Test_Harness();
+  Init_Test_Harness("basic");
+  // This call initializes the test harness.
+  // The string you pass in will be prefixed to all test names.
+  // (you can omit the prefix if you want.)
 
-  Test("basic test", () {
+  // This is how you create a single test.
+  // A test is a logically connected unit of functionality you
+  // want to verify the results of.
+  Test("example test", () {
     expect(times2(1), 2);
     expect(times2(2), 4);
   });
 
+  // You can have more than one test in a suite.
+  Test("example test 2", () {
+    expect(times2(3), 6);
+
+    // uncomment this next expect call to see what it's like when
+    // a test fails
+    // expect(times2(4), 3);
+  });
+
   Run_Test_Harness();
+  // when you're done declaring tests, call Run_Test_Harness
+  // to actually run all the tests and output the results
+
+  // This test will never run because it's being declared after
+  // Run_Test_Harness. We don't have a good way to check this and
+  // alert you automatically right now so be careful
+  Test("bad test", () {
+    expect(times2(4), 3);
+  });
 }
diff --git a/tests/before_after.gs_test.jai b/tests/before_after.gs_test.jai
index 2846a20..fafa510 100644
--- a/tests/before_after.gs_test.jai
+++ b/tests/before_after.gs_test.jai
@@ -4,10 +4,13 @@ afters_called := 0;
 main :: () {
   Init_Test_Harness();
 
+  // You can declare a single Before_Each function
+  // that will run before each test in this suite
   Before_Each(() {
     befores_called += 1;
   });
 
+  // Similarly, you can run an After_Each function as well
   After_Each(() {
     afters_called += 1;
   });