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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
37ede11
Initial commit / skip pycharm config
Aug 30, 2021
36628ae
Added essential dependancies
Sep 1, 2021
7dcfb8a
Merge remote-tracking branch 'origin/main' into feature/pytest_implem…
TechnicalPirate Sep 1, 2021
3407d13
Added another developer dependancy + a readme for test execution
TechnicalPirate Sep 1, 2021
9b77e1c
Merge branch 'marcelotduarte:main' into feature/pipenv_dep_management…
TechnicalPirate Sep 3, 2021
34f480d
Fixes for all but one unit test
TechnicalPirate Sep 3, 2021
a27ad4d
Merge branch 'marcelotduarte:main' into feature/fix_tests
TechnicalPirate Sep 27, 2021
1074d9c
Merge branch 'marcelotduarte:main' into feature/pipenv_dep_management…
TechnicalPirate Sep 27, 2021
34bbf76
Added pycharm idea folder to excluded dirs
TechnicalPirate Sep 27, 2021
df9dac9
Updated lock file
TechnicalPirate Sep 27, 2021
ca2b440
Merge branch 'feature/fix_tests' into feature/convert_existing_tests_…
TechnicalPirate Sep 27, 2021
1f7a75e
Initial PyTest setup + import namespace test
TechnicalPirate Sep 27, 2021
07cf1bc
Ported first nose test
TechnicalPirate Sep 27, 2021
a3e9c59
Fully ported test_finder
TechnicalPirate Sep 27, 2021
f3c482f
Moved remaining files
TechnicalPirate Sep 27, 2021
af93b30
Delete old test suite
TechnicalPirate Sep 27, 2021
c28fed2
added some more very basic tests
TechnicalPirate Sep 27, 2021
de7d0ef
Generated dev-requirements
TechnicalPirate Sep 27, 2021
c0642a8
Remove pipenv files
TechnicalPirate Sep 27, 2021
6530818
Ignore pipfiles
TechnicalPirate Sep 27, 2021
2df9638
Merge branch 'main' into feature/pipenv_dep_management_and_test_readme
TechnicalPirate Sep 27, 2021
9087a34
Update Readme.md
TechnicalPirate Sep 27, 2021
efb4dba
Merge branch 'feature/pipenv_dep_management_and_test_readme' into fea…
TechnicalPirate Sep 27, 2021
c48a771
Merge branch 'main' into feature/convert_existing_tests_to_pytest
TechnicalPirate Sep 27, 2021
8e7152e
Cleaning up reports + ignores
TechnicalPirate Sep 27, 2021
001aefd
Removed unimplemented tests + improved param call
TechnicalPirate Sep 28, 2021
9057119
Improve test to avoid ns pollution
TechnicalPirate Sep 28, 2021
55bd656
Merge remote-tracking branch 'origin/main' into feature/convert_exist…
TechnicalPirate Sep 30, 2021
e3833d5
Fix failing test + nuke uneeded file + gitignore update
TechnicalPirate Oct 6, 2021
93dc1c5
Switch approach for handling namesapce test
TechnicalPirate Oct 8, 2021
7b2d3e4
Disabled test temporarily
TechnicalPirate Oct 8, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@ dump.sql
# Don't allow pipenv/piplock files to be directly commited ( usage of `pip` only expected )
*Pipfile
*Pipfile.lock

# ignore 2 locations for pytest coverage reports ( maybe wanted in future? )
/htmlcov
.coverage
tests/coverage_html_report
tests/.coverage
14 changes: 0 additions & 14 deletions test/Readme.md

This file was deleted.

66 changes: 0 additions & 66 deletions test/test_finder.py

This file was deleted.

42 changes: 0 additions & 42 deletions test/test_misc.py

This file was deleted.

45 changes: 0 additions & 45 deletions test/test_zip_packages.py

This file was deleted.

9 changes: 9 additions & 0 deletions tests/.coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[run]
branch = True
include =
../cx_Freeze/*

omit =

[html]
directory = coverage_html_report
23 changes: 23 additions & 0 deletions tests/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
## Test Execution
To Execute the tests in this folder do the following steps

1 - Install the `dev-requirements` dependencies using `pip install -r dev-requirements.txt`

2 - First install the module in development ( as seen in `setup.py`'s doc string )

```
Use one of the following commands to use the development mode:
pip install -e .
python setup.py develop
```

3 - Call the tests (debuggable) with:
```
python -m pytest tests
```

or with coverage (not-debuggable) with:
```
python -m pytest tests -m "not long" --cov="cx_Freeze" --cov-report=html
```
The coverage report will be saved into `/htmlcov` - open the `index.html` to navigate the report
14 changes: 14 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import pytest
import os


@pytest.fixture()
def fix_test_dir():
""" This fixture returns the root of the test folder """
return os.path.dirname(__file__)


@pytest.fixture()
def fix_test_samples_dir(fix_test_dir):
""" This fixture returns the samples folder for the tests """
return os.path.join(fix_test_dir, "samples")
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
46 changes: 46 additions & 0 deletions tests/test___init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import sys
import importlib
import pytest
import cx_Freeze


@pytest.mark.skip(reason="needs updating to handle/mock platform specific imports")
@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)
12 changes: 12 additions & 0 deletions tests/test_exception.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import pytest
from cx_Freeze.exception import ConfigError, DarwinException


@pytest.mark.parametrize("custom_exception", [ConfigError, DarwinException])
def test_raise_exceptions(custom_exception):
""" This method tests that exceptions can be raised + caught and the __str__ value is correctly called """
# TODO : Discuss with maintainer, `ConfigError` dosen't seem like it needs a custom implementation?
try:
raise custom_exception("Something Bad Happened")
except custom_exception as err:
print(str(err)) # Force invokation of the __str__ method
90 changes: 90 additions & 0 deletions tests/test_finder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import os
import sys
import shutil
import zipfile
import pytest
from cx_Freeze import ModuleFinder, Module, ConstantsModule


class TestModuleFinderWithConvertedNoseTests:
""" This class provides test cases that are conversions of the old NoseTests in `test_finder`
that predated usage of the PyTest Framework"""

@pytest.fixture()
def fix_module_finder(self):
constants = ConstantsModule()
mf = ModuleFinder(constants_module=constants)
return mf

def test_ScanCode(self, mocker, fix_test_samples_dir, fix_module_finder):
any3 = (mocker.ANY,) * 3
import_mock = mocker.patch.object(fix_module_finder, "_import_module", return_value=None)
fix_module_finder.IncludeFile(os.path.join(fix_test_samples_dir, "imports_sample.py"))
import_mock.assert_has_calls(
[
mocker.call("moda", *any3),
mocker.call("modb", *any3),
mocker.call("", *any3),
mocker.call("modd", *any3),
mocker.call("mode", *any3),
mocker.call("modf", *any3),
mocker.call("modg.submod", *any3),
mocker.call("modh", *any3),
]
)

def test_not_import_invalid_module_name(self, mocker, fix_test_samples_dir, fix_module_finder):
""" testpkg1 contains not.importable.py, which shouldn't be included."""
fix_module_finder.path.insert(0, fix_test_samples_dir)
module = fix_module_finder.IncludePackage(
"testpkg1"
) # Threw ImportError before the bug was fixed
assert ("invalid-identifier" in module.global_names), \
"submodules whose names contain invalid identifiers should still be imported"

def test_invalid_syntax(self, mocker, fix_test_samples_dir):
"""Invalid syntax (e.g. Py2 or Py3 only code) should not break freezing."""
constants = ConstantsModule()
mf = ModuleFinder(path=[fix_test_samples_dir] + sys.path, constants_module=constants)
with pytest.raises(ImportError):
mf.IncludeModule(
"invalid_syntax"
) # Threw SyntaxError before the bug was fixed

@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 :)

# -----------------
# Helper Methods from `test_zip_packages`
def clean_pyc_files():
for dirpath, dirnames, filenames in os.walk(fix_samples_dir):
for filename in filenames:
if filename.endswith((".pyc", ".pyo")):
os.unlink(os.path.join(dirpath, filename))
if "__pycache__" in dirnames:
dirnames.remove("__pycache__")
shutil.rmtree(os.path.join(dirpath, "__pycache__"))

def prepare_zip_file():
clean_pyc_files()
tmpd = tmpdir.mkdir()
egg = os.path.join(tmpd, "testpkg1.egg")
eggzip = zipfile.PyZipFile(egg, "w", zipfile.ZIP_DEFLATED)
eggzip.writepy(os.path.join(fix_samples_dir, "testmod1.py"))
eggzip.writepy(os.path.join(fix_samples_dir, "testpkg1"))
eggzip.close()
return egg
# End Helper Methods
# -----------------


# Original test
egg = prepare_zip_file()
try:
fix_module_finder.path = [egg]
mod = fix_module_finder._internal_import_module(
"testpkg1.submod", deferred_imports=[]
)
assert isinstance(mod, Module)
finally:
os.unlink(egg)
Loading