Skip to content

Commit

Permalink
Convert existing tests to pytest + increase coverage (#1255)
Browse files Browse the repository at this point in the history
* Added essential dependancies
* Added another developer dependancy + a readme for test execution
* Fixes for all but one unit test
* Disable failing test
* Added pycharm idea folder to excluded dirs
* Initial PyTest setup + import namespace test
* Ported first nose test
* Fully ported test_finder
* Moved remaining files
* Delete old test suite
* added some more very basic tests
* Generated dev-requirements
* Ignore pipfiles
* Update Readme.md
* Cleaning up reports + ignores
* Removed unimplemented tests + improved param call
* Improve test to avoid ns pollution
* Fix failing test + nuke uneeded file + gitignore update
* Switch approach for handling namesapce test
* Disabled test temporarily

Co-authored-by: Joe Deuchar <joe.deuchar@king.com>
  • Loading branch information
TechnicalPirate and Joe Deuchar authored Oct 9, 2021
1 parent 600f315 commit b4e1157
Show file tree
Hide file tree
Showing 20 changed files with 336 additions and 168 deletions.
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.
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):
# -----------------
# 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

0 comments on commit b4e1157

Please sign in to comment.