Repository: cocotb/cocotb

Issue:
Problems with MODULE
If the `MODULE` env variable is not set cocotb fails hard by raising (an `ImportError` of all things...) in the startup routine. It seems to me it should just run and exit with no failure because there are no tests to run.

`MODULE` might also accidentally contain trailing or leading separators, this isn't handled, and tests show it fails in an ugly way. `HOOKS`, whose usefulness is debatable, suffers the same problem.


Discussion:
We should also have a test that ensures things still work when we have `MODULE`, but don't have any tests.

Resolving patch:
diff --git a/cocotb/__init__.py b/cocotb/__init__.py
--- a/cocotb/__init__.py
+++ b/cocotb/__init__.py
@@ -164,12 +164,11 @@ def _initialise_testbench(root_name):
     test_str = os.getenv('TESTCASE')
     hooks_str = os.getenv('COCOTB_HOOKS', '')
 
-    if not module_str:
-        raise ImportError("Environment variables defining the module(s) to " +
-                          "execute not defined.  MODULE=\"%s\"" % (module_str))
+    if module_str is None:
+        raise ValueError("Environment variable MODULE, which defines the module(s) to execute, is not defined.")
 
-    modules = module_str.split(',')
-    hooks = hooks_str.split(',') if hooks_str else []
+    modules = [s.strip() for s in module_str.split(',') if s.strip()]
+    hooks = [s.strip() for s in hooks_str.split(',') if s.strip()]
 
     global regression_manager
 
diff --git a/cocotb/regression.py b/cocotb/regression.py
--- a/cocotb/regression.py
+++ b/cocotb/regression.py
@@ -144,6 +144,7 @@ def initialise(self):
         # Test Discovery
         ####################
 
+        have_tests = False
         for module_name in self._modules:
             try:
                 self.log.debug("Python Path: " + ",".join(sys.path))
@@ -180,6 +181,10 @@ def initialise(self):
             for thing in vars(module).values():
                 if hasattr(thing, "im_test"):
                     self._init_test(thing)
+                    have_tests = True
+
+        if not have_tests:
+            self.log.warning("No tests were discovered")
 
         self._queue.sort(key=lambda test: (test.stage, test._id))
 


Test patch:
diff --git a/tests/test_cases/test_module_var_empty/Makefile b/tests/test_cases/test_module_var_empty/Makefile
new file mode 100644
--- /dev/null
+++ b/tests/test_cases/test_module_var_empty/Makefile
@@ -0,0 +1,5 @@
+include ../../designs/sample_module/Makefile
+
+# test MODULE is empty
+
+MODULE := " "
diff --git a/tests/test_cases/test_module_var_messy/Makefile b/tests/test_cases/test_module_var_messy/Makefile
new file mode 100644
--- /dev/null
+++ b/tests/test_cases/test_module_var_messy/Makefile
@@ -0,0 +1,5 @@
+include ../../designs/sample_module/Makefile
+
+# test MODULE contains leading and trailing separators
+
+MODULE=" , test_nothing  ,"
diff --git a/tests/test_cases/test_module_var_messy/test_nothing.py b/tests/test_cases/test_module_var_messy/test_nothing.py
new file mode 100644
--- /dev/null
+++ b/tests/test_cases/test_module_var_messy/test_nothing.py
@@ -0,0 +1 @@
+""" This test module is purposefully empty """
diff --git a/tests/test_cases/test_module_without_tests/Makefile b/tests/test_cases/test_module_without_tests/Makefile
new file mode 100644
--- /dev/null
+++ b/tests/test_cases/test_module_without_tests/Makefile
@@ -0,0 +1,5 @@
+include ../../designs/sample_module/Makefile
+
+# test MODULE is set, but there are no tests across any of the modules
+
+MODULE=test_nothing
diff --git a/tests/test_cases/test_module_without_tests/test_nothing.py b/tests/test_cases/test_module_without_tests/test_nothing.py
new file mode 100644
--- /dev/null
+++ b/tests/test_cases/test_module_without_tests/test_nothing.py
@@ -0,0 +1 @@
+""" This test module is purposefully empty """