Skip to content

Commit

Permalink
Refactor python build test to improve coverage
Browse files Browse the repository at this point in the history
Switching to a parametrized approach also significantly reduces
duplicated code in the test.
  • Loading branch information
cottsay committed Feb 2, 2024
1 parent 291f16c commit 90701a9
Showing 1 changed file with 74 additions and 112 deletions.
186 changes: 74 additions & 112 deletions test/test_build_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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,
Expand All @@ -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'
Expand All @@ -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)

0 comments on commit 90701a9

Please sign in to comment.