make test: separate test discovery code

Separating test discovery code to it's own script file has the
advantage of easily doing e.g. listing of all existing tests.

Change-Id: I80dc280263cc7e33e7e13cb0d48b39bf08ece24d
Signed-off-by: Klement Sekera <ksekera@cisco.com>
This commit is contained in:
Klement Sekera
2017-08-17 07:38:42 +02:00
committed by Florin Coras
parent 6d157c2f91
commit fcbf44448b
2 changed files with 68 additions and 34 deletions

57
test/discover_tests.py Executable file
View File

@ -0,0 +1,57 @@
#!/usr/bin/env python
import sys
import os
import unittest
import importlib
import argparse
def discover_tests(directory, callback):
do_insert = True
for _f in os.listdir(directory):
f = "%s/%s" % (directory, _f)
if os.path.isdir(f):
discover_tests(f, callback)
continue
if not os.path.isfile(f):
continue
if do_insert:
sys.path.insert(0, directory)
do_insert = False
if not _f.startswith("test_") or not _f.endswith(".py"):
continue
name = "".join(f.split("/")[-1].split(".")[:-1])
if name in sys.modules:
raise Exception("Duplicate test module `%s' found!" % name)
module = importlib.import_module(name)
for name, cls in module.__dict__.items():
if not isinstance(cls, type):
continue
if not issubclass(cls, unittest.TestCase):
continue
if name == "VppTestCase":
continue
for method in dir(cls):
if not callable(getattr(cls, method)):
continue
if method.startswith("test_"):
callback(_f, cls, method)
def print_callback(file_name, cls, method):
print("%s.%s.%s" % (file_name, cls.__name__, method))
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Discover VPP unit tests")
parser.add_argument("-d", "--dir", action='append', type=str,
help="directory containing test files "
"(may be specified multiple times)")
args = parser.parse_args()
if args.dir is None:
args.dir = "."
suite = unittest.TestSuite()
for d in args.dir:
discover_tests(d, print_callback)

View File

@ -5,43 +5,11 @@ import os
import select import select
import unittest import unittest
import argparse import argparse
import importlib
from multiprocessing import Process, Pipe from multiprocessing import Process, Pipe
from framework import VppTestRunner from framework import VppTestRunner
from debug import spawn_gdb from debug import spawn_gdb
from log import global_logger from log import global_logger
from discover_tests import discover_tests
def add_from_dir(suite, directory):
do_insert = True
for _f in os.listdir(directory):
f = "%s/%s" % (directory, _f)
if os.path.isdir(f):
add_from_dir(suite, f)
continue
if not os.path.isfile(f):
continue
if do_insert:
sys.path.insert(0, directory)
do_insert = False
if not _f.startswith("test_") or not _f.endswith(".py"):
continue
name = "".join(f.split("/")[-1].split(".")[:-1])
if name in sys.modules:
raise Exception("Duplicate test module `%s' found!" % name)
module = importlib.import_module(name)
for name, cls in module.__dict__.items():
if not isinstance(cls, type):
continue
if not issubclass(cls, unittest.TestCase):
continue
if name == "VppTestCase":
continue
for method in dir(cls):
if not callable(getattr(cls, method)):
continue
if method.startswith("test_"):
suite.addTest(cls(method))
def test_runner_wrapper(suite, keep_alive_pipe, result_pipe): def test_runner_wrapper(suite, keep_alive_pipe, result_pipe):
@ -54,6 +22,14 @@ def test_runner_wrapper(suite, keep_alive_pipe, result_pipe):
keep_alive_pipe.close() keep_alive_pipe.close()
class add_to_suite_callback:
def __init__(self, suite):
self.suite = suite
def __call__(self, file_name, cls, method):
suite.addTest(cls(method))
def run_forked(suite): def run_forked(suite):
keep_alive_parent_end, keep_alive_child_end = Pipe(duplex=False) keep_alive_parent_end, keep_alive_child_end = Pipe(duplex=False)
result_parent_end, result_child_end = Pipe(duplex=False) result_parent_end, result_child_end = Pipe(duplex=False)
@ -124,9 +100,10 @@ if __name__ == '__main__':
failfast = True if args.failfast == 1 else False failfast = True if args.failfast == 1 else False
suite = unittest.TestSuite() suite = unittest.TestSuite()
cb = add_to_suite_callback(suite)
for d in args.dir: for d in args.dir:
global_logger.info("Adding tests from directory tree %s" % d) global_logger.info("Adding tests from directory tree %s" % d)
add_from_dir(suite, d) discover_tests(d, cb)
if debug is None or debug.lower() not in ["gdb", "gdbserver"]: if debug is None or debug.lower() not in ["gdb", "gdbserver"]:
sys.exit(run_forked(suite)) sys.exit(run_forked(suite))