pytest-dev / pytest-html

Plugin for generating HTML reports for pytest results
Other
691 stars 234 forks source link

packageing pytest with pyinstaller and creating html reports #813

Open fxatNavVis opened 4 months ago

fxatNavVis commented 4 months ago

Hej, we are trying to package pytest into an executable for ubuntu18.04. When packaging it without pytest-html and just creating a xml report, it works fine, with html I get this error:

INTERNALERROR> Traceback (most recent call last):
INTERNALERROR>   File "_pytest/main.py", line 269, in wrap_session
INTERNALERROR>   File "pluggy/_hooks.py", line 513, in __call__
INTERNALERROR>     return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
INTERNALERROR>   File "pluggy/_manager.py", line 120, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
INTERNALERROR>   File "pluggy/_callers.py", line 182, in _multicall
INTERNALERROR>     return outcome.get_result()
INTERNALERROR>   File "pluggy/_result.py", line 100, in get_result
INTERNALERROR>     raise exc.with_traceback(exc.__traceback__)
INTERNALERROR>   File "pluggy/_callers.py", line 103, in _multicall
INTERNALERROR>     res = hook_impl.function(*args)
INTERNALERROR>   File "pytest_html/basereport.py", line 167, in pytest_sessionstart
INTERNALERROR>   File "pytest_html/basereport.py", line 75, in _generate_environment
INTERNALERROR>   File "_pytest/stash.py", line 80, in __getitem__
INTERNALERROR> KeyError: <_pytest.stash.StashKey object at 0x7f7e58c71df0>

The spec file kind of looks like this

# -*- mode: python -*-

from PyInstaller.utils.hooks import collect_dynamic_libs, copy_metadata, collect_data_files, collect_submodules
import os

block_cipher = None

added_files = [
    *copy_metadata('pytest'),
    *copy_metadata('pytest_html'),
    *copy_metadata('pluggy'),
    *collect_data_files('_pytest'),
    *collect_data_files('pytest_html'),
    *collect_data_files('jinja2'),
    *collect_data_files('pluggy', include_py_files=True),
]

# Filter function to check for libstdc++

def filter_libstdcxx(binaries):
    return [(name, path) for name, path in binaries if 'libstdc++' not in os.path.basename(path)]

# Collect binaries without libstdc++.so.6
added_binaries = filter_libstdcxx(collect_dynamic_libs('gtk'))
added_binaries.append(('/usr/lib/x86_64-linux-gnu/libjavascriptcoregtk*', '.'))
added_binaries.append(('/usr/lib/x86_64-linux-gnu/libwebkit2gtk*', '.'))
added_binaries.append(('/usr/lib/x86_64-linux-gnu/webkit2gtk-4.0/injected-bundle/*', '.'))
added_binaries.append(('/3rdpartylib/*.so', '.'))
added_binaries.append(('/3rdpartylib/cycx3*.img', 'resources'))
added_binaries.append(('/3rdpartylib/*.conf', 'resources'))

hidden_imports = [
    'pytest',
    '_pytest',
    'pytest_html',
    'pluggy',
    'jinja2',
    'jinja2.ext',
]

hidden_imports += collect_submodules('pytest') + collect_submodules('pytest_html') + collect_submodules('pluggy')
print(hidden_imports)

a = Analysis(['testbench.py'],
             pathex=['.'],
             binaries=added_binaries,
             datas=added_files,
             hiddenimports=hidden_imports,
             hookspath=['.'],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher)

pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          name='testbench',
          debug=False,
          strip=False,
          upx=True,
          runtime_tmpdir=None,
          console=True,
          icon=None)

Someone solved the key error before or ran into similar problems?

alexweber200 commented 3 months ago

Hi, I had the same issue trying to include the pytest-html plugin in my pyinstaller build. After looking through the source, it looks like the pytest-html report generator retrieves the stash key from pytest-metadata. I resolved the issue by including pytest-metadata in my imports:

hiddenimports += collect_submodules('pytest_metadata')
hiddenimports += collect_submodules('pytest_html')
hiddenimports += collect_submodules('pytest_timeout')

datas += collect_data_files('pytest_metadata')
datas += collect_data_files('pytest_html')
datas += collect_data_files('pytest_timeout')

datas += copy_metadata('pytest_metadata')
datas += copy_metadata('pytest_html')
datas += copy_metadata('pytest_timeout')