From 90701a9d1a439fde17dd1b9f63a70c9586c61977 Mon Sep 17 00:00:00 2001 From: Scott K Logan Date: Fri, 2 Feb 2024 11:52:44 -0600 Subject: [PATCH] Refactor python build test to improve coverage Switching to a parametrized approach also significantly reduces duplicated code in the test. --- test/test_build_python.py | 186 +++++++++++++++----------------------- 1 file changed, 74 insertions(+), 112 deletions(-) diff --git a/test/test_build_python.py b/test/test_build_python.py index 630935f5..b31d4b5c 100644 --- a/test/test_build_python.py +++ b/test/test_build_python.py @@ -45,7 +45,12 @@ def monkey_patch_put_event_into_queue(monkeypatch): ) -def _test_build_package(tmp_path_str, *, symlink_install): +def _test_build_package( + tmp_path_str, *, symlink_install, setup_cfg, libexec_pattern +): + assert not libexec_pattern or setup_cfg, \ + 'The libexec pattern requires use of setup.cfg' + event_loop = new_event_loop() asyncio.set_event_loop(event_loop) try: @@ -54,9 +59,10 @@ def _test_build_package(tmp_path_str, *, symlink_install): package = PackageDescriptor(tmp_path / 'src') package.name = 'test_package' package.type = 'python' - package.metadata['get_python_setup_options'] = lambda _: { - 'packages': ['my_module'], - } + if not setup_cfg: + package.metadata['get_python_setup_options'] = lambda _: { + 'packages': ['my_module'], + } context = TaskContext( pkg=package, @@ -73,101 +79,7 @@ def _test_build_package(tmp_path_str, *, symlink_install): pkg = python_build_task.context.pkg pkg.path.mkdir(exist_ok=True) - (pkg.path / 'setup.py').write_text( - 'from setuptools import setup\n' - 'setup(\n' - ' name="test-package",\n' - ' packages=["my_module"],\n' - ')\n' - ) - (pkg.path / 'my_module').mkdir(exist_ok=True) - (pkg.path / 'my_module' / '__init__.py').touch() - - src_base = Path(python_build_task.context.args.path) - - source_files_before = set(src_base.rglob('*')) - rc = event_loop.run_until_complete(python_build_task.build()) - assert not rc - source_files_after = set(src_base.rglob('*')) - assert source_files_before == source_files_after - - build_base = Path(python_build_task.context.args.build_base) - assert build_base.rglob('my_module/__init__.py') - - return Path(python_build_task.context.args.install_base) - finally: - event_loop.close() - - -def test_build_package(): - with TemporaryDirectory(prefix='test_colcon_') as tmp_path_str: - install_base = _test_build_package(tmp_path_str, symlink_install=False) - - assert 1 == len(list(install_base.rglob('my_module/__init__.py'))) - - pkg_info, = install_base.rglob('PKG-INFO') - assert 'Name: test-package' in pkg_info.read_text().splitlines() - - -def test_build_package_symlink(): - with TemporaryDirectory(prefix='test_colcon_') as tmp_path_str: - install_base = _test_build_package(tmp_path_str, symlink_install=True) - - assert 1 == len(list(install_base.rglob('test-package.egg-link'))) - - -def test_build_package_symlink_first(): - with TemporaryDirectory(prefix='test_colcon_') as tmp_path_str: - install_base = _test_build_package(tmp_path_str, symlink_install=True) - - assert 1 == len(list(install_base.rglob('test-package.egg-link'))) - assert 0 == len(list(install_base.rglob('PKG-INFO'))) - - install_base = _test_build_package(tmp_path_str, symlink_install=False) - - assert 0 == len(list(install_base.rglob('test-package.egg-link'))) - assert 1 == len(list(install_base.rglob('PKG-INFO'))) - - -def test_build_package_symlink_second(): - with TemporaryDirectory(prefix='test_colcon_') as tmp_path_str: - install_base = _test_build_package(tmp_path_str, symlink_install=False) - - assert 0 == len(list(install_base.rglob('test-package.egg-link'))) - assert 1 == len(list(install_base.rglob('PKG-INFO'))) - - install_base = _test_build_package(tmp_path_str, symlink_install=True) - - assert 1 == len(list(install_base.rglob('test-package.egg-link'))) - assert 0 == len(list(install_base.rglob('PKG-INFO'))) - - -def test_build_package_libexec_pattern(): - event_loop = new_event_loop() - asyncio.set_event_loop(event_loop) - try: - with TemporaryDirectory(prefix='test_colcon_') as tmp_path_str: - tmp_path = Path(tmp_path_str) - python_build_task = PythonBuildTask() - package = PackageDescriptor(tmp_path / 'src') - package.name = 'test_package' - package.type = 'python' - - context = TaskContext( - pkg=package, - args=SimpleNamespace( - path=str(tmp_path / 'src'), - build_base=str(tmp_path / 'build'), - install_base=str(tmp_path / 'install'), - symlink_install=False, - ), - dependencies={} - ) - python_build_task.set_context(context=context) - - pkg = python_build_task.context.pkg - - pkg.path.mkdir(exist_ok=True) + if setup_cfg: (pkg.path / 'setup.py').write_text( 'from setuptools import setup\n' 'setup()\n' @@ -180,22 +92,72 @@ def test_build_package_libexec_pattern(): '[options.entry_points]\n' 'console_scripts =\n' ' my_command = my_module:main\n' - '[develop]\n' - 'script-dir=$base/lib/test_package\n' - '[install]\n' - 'install-scripts=$base/lib/test_package\n' + + ( + '[develop]\n' + 'script-dir=$base/lib/test_package\n' + '[install]\n' + 'install-scripts=$base/lib/test_package\n' + if libexec_pattern else '' + ) ) - (pkg.path / 'my_module').mkdir(exist_ok=True) - (pkg.path / 'my_module' / '__init__.py').write_text( - 'def main():\n' - ' print("Hello, World!")\n' + else: + (pkg.path / 'setup.py').write_text( + 'from setuptools import setup\n' + 'setup(\n' + ' name="test-package",\n' + ' packages=["my_module"],\n' + ' entry_points={\n' + ' "console_scripts": ["my_command = my_module:main"],\n' + ' },\n' + ')\n' ) + (pkg.path / 'my_module').mkdir(exist_ok=True) + (pkg.path / 'my_module' / '__init__.py').write_text( + 'def main():\n' + ' print("Hello, World!")\n' + ) + + src_base = Path(python_build_task.context.args.path) + + source_files_before = set(src_base.rglob('*')) + rc = event_loop.run_until_complete(python_build_task.build()) + assert not rc + source_files_after = set(src_base.rglob('*')) + assert source_files_before == source_files_after - rc = event_loop.run_until_complete(python_build_task.build()) - assert not rc + build_base = Path(python_build_task.context.args.build_base) + assert build_base.rglob('my_module/__init__.py') - install_base = Path(python_build_task.context.args.install_base) - assert list(install_base.rglob( - '**/lib/test_package/my_command*')) + install_base = Path(python_build_task.context.args.install_base) + assert symlink_install == any(install_base.rglob( + 'test-package.egg-link')) + assert symlink_install != any(install_base.rglob( + 'PKG-INFO')) + assert libexec_pattern == any(install_base.rglob( + '**/lib/test_package/my_command*')) + assert libexec_pattern != any(install_base.rglob( + '**/bin/my_command*')) + + if not symlink_install: + pkg_info, = install_base.rglob('PKG-INFO') + assert 'Name: test-package' in pkg_info.read_text().splitlines() finally: event_loop.close() + + +@pytest.mark.parametrize( + 'symlink_first', + [False, True]) +@pytest.mark.parametrize( + 'setup_cfg,libexec_pattern', + [(False, False), (True, False), (True, True)]) +def test_build_package(symlink_first, setup_cfg, libexec_pattern): + with TemporaryDirectory(prefix='test_colcon_') as tmp_path_str: + _test_build_package( + tmp_path_str, symlink_install=symlink_first, + setup_cfg=setup_cfg, libexec_pattern=libexec_pattern) + + # Test again with the symlink flag inverted to validate cleanup + _test_build_package( + tmp_path_str, symlink_install=not symlink_first, + setup_cfg=setup_cfg, libexec_pattern=libexec_pattern)