From 3114bc65885a7499f5a255e76875fa88010e8589 Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Sat, 13 Jul 2024 13:25:02 +0200 Subject: unittests: allow running with pytest/unittest directly Currently the unittests are not runnable with pytest or unittest without going through the run_unittests.py wrapper, or setting certain env vars like MESON_UNIT_TEST_BACKEND. This has that downside that the common "pytest ..." fails and integration with things like VSCode fails too. To work around that we set everything that is needed to run the tests in __init__.py and run_unittests is only one more variant to invoke them by providing different defaults and settings. To make sure that pytest/unittest discover and run_unittests don't diverge implement an automatic test discovery in run_unittests to avoid hardcoding the tests to run there. There shouldn't be any functional changes. --- run_unittests.py | 67 +++++++++++++++++++++------------------------------ unittests/__init__.py | 20 +++++++++++++++ 2 files changed, 47 insertions(+), 40 deletions(-) diff --git a/run_unittests.py b/run_unittests.py index 84edb34cc..6a84f5c05 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -11,43 +11,12 @@ import time import subprocess import os import unittest +import importlib +import typing as T -import mesonbuild.mlog -import mesonbuild.depfile -import mesonbuild.dependencies.base -import mesonbuild.dependencies.factory -import mesonbuild.compilers -import mesonbuild.envconfig -import mesonbuild.environment import mesonbuild.coredata -import mesonbuild.modules.gnome from mesonbuild.mesonlib import python_command, setup_vsenv -import mesonbuild.modules.pkgconfig -from unittests.allplatformstests import AllPlatformTests -from unittests.cargotests import CargoVersionTest, CargoCfgTest, CargoLockTest -from unittests.darwintests import DarwinTests -from unittests.failuretests import FailureTests -from unittests.linuxcrosstests import LinuxCrossArmTests, LinuxCrossMingwTests -from unittests.machinefiletests import NativeFileTests, CrossFileTests -from unittests.rewritetests import RewriterTests -from unittests.taptests import TAPParserTests -from unittests.datatests import DataTests -from unittests.internaltests import InternalTests -from unittests.linuxliketests import LinuxlikeTests -from unittests.pythontests import PythonTests -from unittests.subprojectscommandtests import SubprojectsCommandTests -from unittests.windowstests import WindowsTests -from unittests.platformagnostictests import PlatformAgnosticTests - -def unset_envs(): - # For unit tests we must fully control all command lines - # so that there are no unexpected changes coming from the - # environment, for example when doing a package build. - varnames = ['CPPFLAGS', 'LDFLAGS'] + list(mesonbuild.compilers.compilers.CFLAGS_MAPPING.values()) - for v in varnames: - if v in os.environ: - del os.environ[v] def convert_args(argv): # If we got passed a list of tests, pass it on @@ -100,15 +69,33 @@ def setup_backend(): os.environ['MESON_UNIT_TEST_BACKEND'] = be sys.argv = filtered +def import_test_cases(suite: unittest.TestSuite) -> T.Set[str]: + ''' + Imports all test classes into the current module and returns their names + ''' + classes = set() + for test in suite: + if isinstance(test, unittest.TestSuite): + classes.update(import_test_cases(test)) + elif isinstance(test, unittest.TestCase): + mod = importlib.import_module(test.__module__) + class_name = test.__class__.__name__ + test_class = getattr(mod, class_name) + classes.add(class_name) + setattr(sys.modules[__name__], class_name, test_class) + return classes + +def discover_test_cases() -> T.Set[str]: + current_dir = os.path.dirname(os.path.realpath(__file__)) + loader = unittest.TestLoader() + suite = loader.discover(os.path.join(current_dir, 'unittests'), '*tests.py', current_dir) + if loader.errors: + raise SystemExit(loader.errors) + return import_test_cases(suite) + def main(): - unset_envs() + cases = sorted(discover_test_cases()) setup_backend() - cases = ['InternalTests', 'DataTests', 'AllPlatformTests', 'FailureTests', - 'PythonTests', 'NativeFileTests', 'RewriterTests', 'CrossFileTests', - 'TAPParserTests', 'SubprojectsCommandTests', 'PlatformAgnosticTests', - - 'LinuxlikeTests', 'LinuxCrossArmTests', 'LinuxCrossMingwTests', - 'WindowsTests', 'DarwinTests'] try: import pytest # noqa: F401 diff --git a/unittests/__init__.py b/unittests/__init__.py index e69de29bb..fb8fb8e85 100644 --- a/unittests/__init__.py +++ b/unittests/__init__.py @@ -0,0 +1,20 @@ +import os + +import mesonbuild.compilers +from mesonbuild.mesonlib import setup_vsenv + +def unset_envs(): + # For unit tests we must fully control all command lines + # so that there are no unexpected changes coming from the + # environment, for example when doing a package build. + varnames = ['CPPFLAGS', 'LDFLAGS'] + list(mesonbuild.compilers.compilers.CFLAGS_MAPPING.values()) + for v in varnames: + if v in os.environ: + del os.environ[v] + +def set_envs(): + os.environ.setdefault('MESON_UNIT_TEST_BACKEND', 'ninja') + +setup_vsenv() +unset_envs() +set_envs() -- cgit v1.2.3