Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert existing tests to pytest + increase coverage #1255

Conversation

TechnicalPirate
Copy link
Contributor

@TechnicalPirate TechnicalPirate commented Sep 27, 2021

Problem - Unit test coverage of the cx_freeze project is very low - prior to Pull-1234 the majority were also not working.

Improving test coverage of the product code will support development of cx_freeze by enabling developers and contributors to have a degree of confidence that there changes are non-destructive to existing functionality and expected usage.

Proposed Solution - This PR replaces the existing nose tests with a pytest suite preconfigured to generate coverage reports as required ( Article here going over benefits of PyTest ) as well as these new tests:

  • test__init__.py -> test_exposed_namespaces
  • test_exception -> test_raise_exceptions
  • test_winmsvcr.py -> test_FILES & test_FILES_TO_DUPLICATE
  • test_winversioninfo.py -> test___init__ and test___init__pads_short_versions

A readme.md is provided in the /tests folder explaining how to execute the tests.

With this PR total coverage of the suite is raised to 27%

image

... While this is in review - i will begin writing coverage for more modules ( slowly building up to addressing : Issue-594

@TechnicalPirate TechnicalPirate changed the title Feature/convert existing tests to pytest convert existing tests to pytest + Extend coverage Sep 27, 2021
@TechnicalPirate TechnicalPirate changed the title convert existing tests to pytest + Extend coverage Convert existing tests to pytest + increase coverage Sep 27, 2021
@TechnicalPirate
Copy link
Contributor Author

TechnicalPirate commented Sep 27, 2021

@marcelotduarte - Thanks for reviewing / deciding on outcomes to the other PR's - with those done i have now updated this PR.

Please feel free to try executing the tests and generating the coverage report and let me know what you think. - If you like this direction I'll prepare this branch as it stands for merging Branch prepared/cleaned and I'll open other PR's module by module as i write test coverage to keep things flowing

Cheers and have a good day/night! :)

@TechnicalPirate TechnicalPirate marked this pull request as ready for review September 28, 2021 09:50
@marcelotduarte
Copy link
Owner

Hi! In two or three days I'll try to make time to test and review. Good afternoon! ;-)

@TechnicalPirate
Copy link
Contributor Author

No stress, Just wanted to square this one up so i could start on the more complex modules.

I may start suggesting small refactors on those other PR's to make code more "testable" :)

Copy link
Owner

@marcelotduarte marcelotduarte left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.coverage should be ignored at .gitignore?


@pytest.mark.skip("Test skipped, uncertain if no longer supported - waiting for maintainer to comment on:"
"https://github.com/marcelotduarte/cx_Freeze/pull/1234")
def test_FindModule_from_zip(self, fix_module_finder, fix_samples_dir, tmpdir):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test can be marked as skipped for now. In the rewrite of ModuleFinder, I ignored this method, but similar support for importing directing from the wheel (.whl)... Maybe we can delete it. I'll think about it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your shout - the current usage of @pytest.mark.skip disables execution of the test - if you want to remove the underlying code + test go for it. I didn't want to remove existing tests without discussion with you :)

@marcelotduarte
Copy link
Owner

In windows:

========================================================= test session starts =========================================================
platform win32 -- Python 3.8.10, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: c:\clone\cx_Freeze
plugins: cov-2.12.1, mock-3.6.1, timeout-1.4.2
collected 15 items

tests\test___init__.py ....                                                                                                      [ 26%]
tests\test_exception.py ..                                                                                                       [ 40%]
tests\test_finder.py ...s                                                                                                        [ 66%]
tests\test_winmsvcr.py ..                                                                                                        [ 80%]
tests\test_winversioninfo.py ...                                                                                                 [100%]

---------- coverage: platform win32, python 3.8.10-final-0 -----------
Coverage HTML written to dir htmlcov


=================================================== 14 passed, 1 skipped in 20.44s ====================================================

In Linux:

==================================================== test session starts =====================================================
platform linux -- Python 3.9.5, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: /home/marcelo/github/cx_Freeze
plugins: mock-3.6.1, timeout-1.4.2, cov-2.12.1
collected 15 items                                                                                                           

tests/test___init__.py .F..                                                                                            [ 26%]
tests/test_exception.py ..                                                                                             [ 40%]
tests/test_finder.py ...s                                                                                              [ 66%]
tests/test_winmsvcr.py ..                                                                                              [ 80%]
tests/test_winversioninfo.py ...                                                                                       [100%]

========================================================== FAILURES ==========================================================
_______________________________________ test_exposed_namespaces[win32-extra_modules1] ________________________________________

mocker = <pytest_mock.plugin.MockerFixture object at 0x7f757f3cfb20>, platform = 'win32', extra_modules = ['bdist_msi']

    @pytest.mark.parametrize(
        "platform, extra_modules",
        [
            (None, []),
            ("win32", ["bdist_msi"]),
            ("darwin", ["bdist_dmg", "bdist_mac"]),
            ("linux", []),
        ],
    )
    def test_exposed_namespaces(mocker, platform, extra_modules):
        """This test asserts that all the namespaces that should be exposed when `importing cx_Freeze` are available"""
        if platform:  # Mock platform before import :)
            mocker.patch.object(sys, "platform", platform)
    
>       importlib.reload(cx_Freeze)

tests/test___init__.py:21: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/usr/lib/python3.9/importlib/__init__.py:169: in reload
    _bootstrap._exec(spec, module)
<frozen importlib._bootstrap>:613: in _exec
    ???
<frozen importlib._bootstrap_external>:855: in exec_module
    ???
<frozen importlib._bootstrap>:228: in _call_with_frames_removed
    ???
cx_Freeze/__init__.py:25: in <module>
    from .windist import bdist_msi
cx_Freeze/windist.py:1: in <module>
    import distutils.command.bdist_msi
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    """
    Implements the bdist_msi command.
    """
    
    import os
    import sys
    import warnings
    from distutils.core import Command
    from distutils.dir_util import remove_tree
    from distutils.sysconfig import get_python_version
    from distutils.version import StrictVersion
    from distutils.errors import DistutilsOptionError
    from distutils.util import get_platform
    from distutils import log
>   import msilib
E   ModuleNotFoundError: No module named 'msilib'

/usr/lib/python3.9/distutils/command/bdist_msi.py:19: ModuleNotFoundError
================================================== short test summary info ===================================================
FAILED tests/test___init__.py::test_exposed_namespaces[win32-extra_modules1] - ModuleNotFoundError: No module named 'msilib'
========================================== 1 failed, 13 passed, 1 skipped in 8.57s ===========================================

@TechnicalPirate
Copy link
Contributor Author

TechnicalPirate commented Oct 6, 2021

.coverage should be ignored at .gitignore?

There's 2 coverage files, one is the db used to generate the report (this is the one in the .gitignore ) the other is the .coveragerc which is a configuration file for which modules to be included in the report - this we should keep checked in :)

import msilib
E ModuleNotFoundError: No module named 'msilib'

Makes sense! - Prob will fail on OSX as well 🤔 ... contemplating how to handle this for testing - will get back to you....

@marcelotduarte
Copy link
Owner

marcelotduarte commented Oct 6, 2021

.coverage should be ignored at .gitignore?

There's 2 coverage files, one is the db used to generate the report (this is the one in the .gitignore ) the other is the .coveragerc which is a configuration file for which modules to be included in the report - this we should keep checked in :)

I'm talking about a binary (db) file that appears as first file at https://github.com/marcelotduarte/cx_Freeze/pull/1255/files
It is not in .gitignore

@TechnicalPirate
Copy link
Contributor Author

Oh bugger! well spotted :) will fix ( am fixing failing test right now - gimmi 10min :) )

@TechnicalPirate
Copy link
Contributor Author

@marcelotduarte - Test should be fixed now + excess file nuked + gitignore updated :)

@marcelotduarte
Copy link
Owner

==================================================== test session starts =====================================================
platform linux -- Python 3.9.5, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: /home/marcelo/github/cx_Freeze
plugins: mock-3.6.1, timeout-1.4.2, cov-2.12.1
collected 15 items                                                                                                           

tests/test___init__.py .F..                                                                                            [ 26%]
tests/test_exception.py ..                                                                                             [ 40%]
tests/test_finder.py ...s                                                                                              [ 66%]
tests/test_winmsvcr.py ..                                                                                              [ 80%]
tests/test_winversioninfo.py ...                                                                                       [100%]

========================================================== FAILURES ==========================================================
_______________________________________ test_exposed_namespaces[win32-extra_modules1] ________________________________________

mocker = <pytest_mock.plugin.MockerFixture object at 0x7f86e1ff2040>, platform = 'win32', extra_modules = ['bdist_msi']

    @pytest.mark.parametrize(
        "platform, extra_modules", [
            (None, []),
            ("win32", ["bdist_msi"]),
            ("darwin", ["bdist_dmg", "bdist_mac"]),
            ("linux", [])
        ]
    )
    def test_exposed_namespaces(mocker, platform, extra_modules):
        """ This test asserts that all the namespaces that should be exposed when `importing cx_Freeze` are available """
        # Mock platform specific modules so we don't get import errors due modules not being available on test device
        platform_specific_modules = ["msilib", ]
        for mod_name in platform_specific_modules:
            fake_mod = types.ModuleType(mod_name)
            sys.modules[mod_name] = fake_mod
    
        if platform:  # Mock platform before import :)
            mocker.patch.object(sys, "platform", platform)
    
>       importlib.reload(cx_Freeze)

tests/test___init__.py:27: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/usr/lib/python3.9/importlib/__init__.py:169: in reload
    _bootstrap._exec(spec, module)
<frozen importlib._bootstrap>:613: in _exec
    ???
<frozen importlib._bootstrap_external>:855: in exec_module
    ???
<frozen importlib._bootstrap>:228: in _call_with_frames_removed
    ???
cx_Freeze/__init__.py:25: in <module>
    from .windist import bdist_msi
cx_Freeze/windist.py:1: in <module>
    import distutils.command.bdist_msi
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    """
    Implements the bdist_msi command.
    """
    
    import os
    import sys
    import warnings
    from distutils.core import Command
    from distutils.dir_util import remove_tree
    from distutils.sysconfig import get_python_version
    from distutils.version import StrictVersion
    from distutils.errors import DistutilsOptionError
    from distutils.util import get_platform
    from distutils import log
    import msilib
>   from msilib import schema, sequence, text
E   ImportError: cannot import name 'schema' from 'msilib' (unknown location)

/usr/lib/python3.9/distutils/command/bdist_msi.py:20: ImportError

----------- coverage: platform linux, python 3.9.5-final-0 -----------
Coverage HTML written to dir htmlcov

================================================== short test summary info ===================================================
FAILED tests/test___init__.py::test_exposed_namespaces[win32-extra_modules1] - ImportError: cannot import name 'schema' fro...
========================================== 1 failed, 13 passed, 1 skipped in 13.07s ==========================================

@TechnicalPirate
Copy link
Contributor Author

Bah! Ok - will fix that up later - watch this space :)

@TechnicalPirate
Copy link
Contributor Author

@marcelotduarte - sorry for delay, have changed approach slightly lets see if it passes now

( Will happily refine tests later, but right now would like to get framework switched over so i can move onto the other tests :) )

@marcelotduarte
Copy link
Owner

==================================================== test session starts =====================================================
platform linux -- Python 3.9.5, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: /home/marcelo/github/cx_Freeze
plugins: mock-3.6.1, timeout-1.4.2, cov-2.12.1
collected 15 items                                                                                                           

tests/test___init__.py .F..                                                                                            [ 26%]
tests/test_exception.py ..                                                                                             [ 40%]
tests/test_finder.py ...s                                                                                              [ 66%]
tests/test_winmsvcr.py ..                                                                                              [ 80%]
tests/test_winversioninfo.py ...                                                                                       [100%]

========================================================== FAILURES ==========================================================
_______________________________________ test_exposed_namespaces[win32-extra_modules1] ________________________________________

mocker = <pytest_mock.plugin.MockerFixture object at 0x7f7335bad6a0>, platform = 'win32', extra_modules = ['bdist_msi']

    @pytest.mark.parametrize(
        "platform, extra_modules", [
            (None, []),
            ("win32", ["bdist_msi"]),
            ("darwin", ["bdist_dmg", "bdist_mac"]),
            ("linux", [])
        ]
    )
    def test_exposed_namespaces(mocker, platform, extra_modules):
        """ This test asserts that all the namespaces that should be exposed when `importing cx_Freeze` are available """
    
        if platform:  # Mock platform before import :)
            mocker.patch.object(sys, "platform", platform)
    
        try:
            importlib.reload(cx_Freeze)
        except ImportError:
            pass  # Pass import errors as some modules are platform specific, we're testing what's exposed in `__all__` here
    
        expected_namespaces = [  # These namespaces are there regardless of platform
            "bdist_rpm",
            "build",
            "build_exe",
            "install",
            "install_exe",
            "setup",
            "ConfigError",
            "ConstantsModule",
            "Executable",
            "Freezer",
            "Module",
            "ModuleFinder",
        ]
        for ns in expected_namespaces:
            assert ns in dir(cx_Freeze)
    
        if platform:
            for ns in extra_modules:
>               assert ns in dir(cx_Freeze)
E               AssertionError: assert 'bdist_msi' in ['ConfigError', 'ConstantsModule', 'Executable', 'Freezer', 'Module', 'ModuleFinder', ...]
E                +  where ['ConfigError', 'ConstantsModule', 'Executable', 'Freezer', 'Module', 'ModuleFinder', ...] = dir(cx_Freeze)

tests/test___init__.py:45: AssertionError

----------- coverage: platform linux, python 3.9.5-final-0 -----------
Coverage HTML written to dir htmlcov

================================================== short test summary info ===================================================
FAILED tests/test___init__.py::test_exposed_namespaces[win32-extra_modules1] - AssertionError: assert 'bdist_msi' in ['Conf...
========================================== 1 failed, 13 passed, 1 skipped in 13.34s ==========================================

@TechnicalPirate
Copy link
Contributor Author

Bah! Ok - Disabled the test for now to unblock the PR. I'll address this in a future PR :)

@marcelotduarte
Copy link
Owner

I think that you can use skipif in the non-windows platform.

@TechnicalPirate
Copy link
Contributor Author

yep i'll split the test into platform specific tests for the platform specific modules - for now ive just disabled the whole thing as its a "New" test and i don't want it to get in the way if you approve of the move to pytest :)

@marcelotduarte marcelotduarte merged commit b4e1157 into marcelotduarte:main Oct 9, 2021
@marcelotduarte
Copy link
Owner

marcelotduarte commented Oct 9, 2021

I merged so you can adjust. If you can make small patches to facilitate it will be good, but when this is not possible, for now, in this part of adjusting the tests, no problem.
Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants