Skip to content

Commit

Permalink
Merge 4f25928 into b278069
Browse files Browse the repository at this point in the history
  • Loading branch information
macisamuele committed Jun 20, 2023
2 parents b278069 + 4f25928 commit fad7941
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 56 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ jobs:
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install virtualenv
run: pip install virtualenv
- name: Run Tests
run: TESTSLIDE_FORMAT=progress UNITTEST_VERBOSE=0 make ci V=1
- name: Coveralls
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ TestSlide.egg-info/
*.vsix
**/package-lock.json
.coverage.lcov
venv/
111 changes: 57 additions & 54 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,27 @@ endif

.PHONY: all
all: tests coverage_report docs sdist
@true

##
## Venv
##
venv: requirements-dev.txt requirements.txt
@printf "${TERM_BRIGHT}CREATE VIRTUALENV (${CURDIR}/venv)\n${TERM_NONE}"
${Q} python3 -m virtualenv venv
@printf "${TERM_BRIGHT}INSTALL BUILD DEPS\n${TERM_NONE}"
${Q} ${CURDIR}/venv/bin/pip install -r requirements-dev.txt
@printf "${TERM_BRIGHT}INSTALL DEPS\n${TERM_NONE}"
${Q} ${CURDIR}/venv/bin/pip install -r requirements.txt

##
## Docs
##

.PHONY: docs
docs:
docs: venv
@printf "${TERM_BRIGHT}DOCS\n${TERM_NONE}"
${Q} make -C docs/ html
${Q} ${MAKE} SPHINXBUILD=${CURDIR}/venv/bin/sphinx-build -C docs/ html

.PHONY: docs_clean
docs_clean:
Expand All @@ -54,30 +66,31 @@ docs_clean:
## Tests
##

%_unittest.py: coverage_erase
%_unittest.py: venv coverage_erase
@printf "${TERM_BRIGHT}UNITTEST $@\n${TERM_NONE}"
${Q} coverage run \
${Q} ${CURDIR}/venv/bin/coverage run \
-m unittest \
${UNITTEST_ARGS} \
--failfast \
$@

.PHONY: unittest_tests
unittest_tests: $(TESTS_SRCS)/*_unittest.py
@true

.PHONY: pytest_tests
pytest_tests: export PYTHONPATH=${CURDIR}/pytest-testslide:${CURDIR}
pytest_tests: coverage_erase
pytest_tests: venv coverage_erase
@printf "${TERM_BRIGHT}INSTALL pytest_testslide DEPS ${TERM_NONE}\n"
${Q} pip install -r pytest-testslide/requirements.txt
${Q} ${CURDIR}/venv/bin/pip install -r pytest-testslide/requirements.txt
@printf "${TERM_BRIGHT}PYTEST pytest_testslide${TERM_NONE}\n"
${Q} coverage run \
${Q} ${CURDIR}/venv/bin/coverage run \
-m pytest \
pytest-testslide/tests

%_testslide.py: coverage_erase
%_testslide.py: venv coverage_erase
@printf "${TERM_BRIGHT}TESTSLIDE $@\n${TERM_NONE}"
${Q} coverage run \
${Q} ${CURDIR}/venv/bin/coverage run \
-m testslide.cli \
--format $(TESTSLIDE_FORMAT) \
--show-testslide-stack-trace \
Expand All @@ -87,41 +100,42 @@ pytest_tests: coverage_erase

.PHONY: testslide_tests coverage_erase
testslide_tests: $(TESTS_SRCS)/*_testslide.py
@true

.PHONY: mypy
mypy:
mypy: venv
@printf "${TERM_BRIGHT}MYPY ${ALL_SRCS}\n${TERM_NONE}"
${Q} mypy ${ALL_SRCS}
${Q} ${CURDIR}/venv/bin/mypy ${ALL_SRCS}

.PHONY: mypy_clean
mypy_clean:
@printf "${TERM_BRIGHT}MYPY CLEAN\n${TERM_NONE}"
${Q} rm -rf .mypy_cache/

.PHONY: flake8
flake8:
flake8: venv
@printf "${TERM_BRIGHT}FLAKE8 ${ALL_SRCS}\n${TERM_NONE}"
${Q} flake8 --select=F,C90 $(ALL_SRCS)
${Q} ${CURDIR}/venv/bin/flake8 --select=F,C90 $(ALL_SRCS)

.PHONY: black
black:
black: venv
@printf "${TERM_BRIGHT}BLACK ${ALL_SRCS}\n${TERM_NONE}"
${Q} black --check $(ALL_SRCS) || { echo "Formatting errors found, try running 'make format'."; exit 1; }
${Q} ${CURDIR}/venv/bin/black --check $(ALL_SRCS) || { echo "Formatting errors found, try running 'make format'."; exit 1; }

.PHONY: isort
isort:
isort: venv
@printf "${TERM_BRIGHT}ISORT ${ALL_SRCS}\n${TERM_NONE}"
${Q} isort --check-only --profile black $(ALL_SRCS) || { echo "Formatting errors found, try running 'make format'."; exit 1; }
${Q} ${CURDIR}/venv/bin/isort --check-only --profile black $(ALL_SRCS) || { echo "Formatting errors found, try running 'make format'."; exit 1; }

.PHONY: format_isort
format_isort:
format_isort: venv
@printf "${TERM_BRIGHT}FORMAT PYFMT ${ALL_SRCS}\n${TERM_NONE}"
${Q} isort --profile black $(ALL_SRCS)
${Q} ${CURDIR}/venv/bin/isort --profile black $(ALL_SRCS)

.PHONY: format_black
format_black:
format_black: venv
@printf "${TERM_BRIGHT}FORMAT BLACK ${ALL_SRCS}\n${TERM_NONE}"
${Q} black $(ALL_SRCS)
${Q} ${CURDIR}/venv/bin/black $(ALL_SRCS)

.PHONY: tests
tests: \
Expand All @@ -138,83 +152,72 @@ tests: \
format: \
format_isort \
format_black

@true
##
## Coverage
##

.PHONY: coverage_erase
coverage_erase:
@printf "${TERM_BRIGHT}COVERAGE ERASE\n${TERM_NONE}"
${Q} coverage erase
${Q} rm -rf ${CURDIR}/.coverage ${CURDIR}/.coverage.*

.PHONY: coverage_combine
coverage_combine: unittest_tests testslide_tests
coverage_combine: venv unittest_tests testslide_tests
@printf "${TERM_BRIGHT}COVERAGE COMBINE\n${TERM_NONE}"
${Q} coverage combine
${Q} ${CURDIR}/venv/bin/coverage combine

.PHONY: coverage_report
coverage_report: coverage_combine
coverage_report: venv coverage_combine
@printf "${TERM_BRIGHT}COVERAGE REPORT\n${TERM_NONE}"
${Q} coverage report
${Q} ${CURDIR}/venv/bin/coverage report

.PHONY: coverage_html
coverage_html: coverage_combine
coverage_html: venv coverage_combine
@printf "${TERM_BRIGHT}COVERAGE HTML\n${TERM_NONE}"
${Q} coverage html
${Q} ${CURDIR}/venv/bin/coverage html

.PHONY: coverage_html_clean
coverage_html_clean:
@printf "${TERM_BRIGHT}COVERAGE HTML CLEAN\n${TERM_NONE}"
${Q} rm -rf htmlcov/

.PHONY: coveralls
coveralls: coverage_combine
coveralls: venv coverage_combine
@printf "${TERM_BRIGHT}COVERALLS\n${TERM_NONE}"
${Q} coveralls
${Q} ${CURDIR}/venv/bin/coveralls

##
## Build
##

.PHONY: install_build_deps
install_build_deps:
@printf "${TERM_BRIGHT}INSTALL BUILD DEPS\n${TERM_NONE}"
${Q} pip install -r requirements.txt
${Q} pip install -r requirements-dev.txt

.PHONY: install_deps
install_deps:
@printf "${TERM_BRIGHT}INSTALL DEPS\n${TERM_NONE}"
${Q} pip install -r requirements.txt

.PHONY: sdist
sdist:
@printf "${TERM_BRIGHT}SDIST\n${TERM_NONE}"
${Q} python setup.py sdist
${Q} python3 setup.py sdist

.PHONY: sdist_clean
sdist_clean:
@printf "${TERM_BRIGHT}SDIST CLEAN\n${TERM_NONE}"
${Q} rm -rf dist/ MANIFEST TestSlide.egg-info/

.PHONY: twine
twine: sdist
twine upload $(DIST_TAR_GZ)
twine: venv sdist
${CURDIR}/venv/bin/twine upload $(DIST_TAR_GZ)

.PHONY: install_local
install_local: sdist
install_local: venv sdist
@printf "${TERM_BRIGHT}INSTALL LOCAL\n${TERM_NONE}"
${Q} pip install $(DIST_TAR_GZ)
${Q} testslide --help
${Q} ${CURDIR}/venv/bin/pip install $(DIST_TAR_GZ)
${Q} ${CURDIR}/venv/bin/testslide --help

.PHONY: build_dev_container
dev_container:
dev_container:
@printf "${TERM_BRIGHT}BUILDING DEV CONTAINER\n${TERM_NONE}"
${Q} docker build -t testslide-dev .

.PHONY: run_tests_in_container
run_tests_in_container:
run_tests_in_container:
@printf "${TERM_BRIGHT}RUNNING CI IN DEV CONTAINER\n${TERM_NONE}"
${Q} docker run testslide-dev

Expand Down Expand Up @@ -244,13 +247,13 @@ clean_dev_container:

.PHONY: ci
ci: \
install_deps \
install_build_deps \
venv \
tests \
coverage_report \
docs \
sdist \
install_local
@true

##
## Clean
Expand All @@ -259,9 +262,9 @@ ci: \
.PHONY: clean
clean: sdist_clean docs_clean coverage_html_clean coverage_erase mypy_clean
@printf "${TERM_BRIGHT}CLEAN\n${TERM_NONE}"
${Q} rm -rf */__pycache__/ */*.pyc
${Q} rm -rf */__pycache__/ */*.pyc venv/


.PHONY: check-copyright
check-copyright: ## verify copyright for every file
@python tests/copyright_check/copyright_validator.py
@python3 tests/copyright_check/copyright_validator.py
8 changes: 8 additions & 0 deletions tests/mock_async_callable_testslide.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ async def cleanup_patches(self):
## Shared Contexts
##

@context.example
async def patching_functions_in_slotted_class(self):
t = sample_module.SomeClassWithSlots(attribute="value")
self.mock_async_callable(t, "async_method").to_return_value(
42
).and_assert_called_once()
self.assertEqual(await t.async_method(), 42)

@context.shared_context
def mock_async_callable_with_sync_examples(context, can_mock_with_flag=True):
@context.example
Expand Down
6 changes: 6 additions & 0 deletions tests/mock_callable_testslide.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ def patching_private_functions_with_allow_private(self):
).and_assert_called_once()
t._privatefun()

@context.example
def patching_functions_in_slotted_class(self):
t = sample_module.SomeClassWithSlots(attribute="value")
self.mock_callable(t, "method").to_return_value(42).and_assert_called_once()
self.assertEqual(t.method(), 42)

##
## Shared Contexts
##
Expand Down
13 changes: 13 additions & 0 deletions tests/sample_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,19 @@ def instance_method_with_star_args(
return 3


class SomeClassWithSlots:
__slots__ = ("attribute",)

def __init__(self, attribute: str) -> None:
self.attribute = attribute

def method(self) -> int:
return 0

async def async_method(self) -> int:
return 0


class TargetStr:
def __str__(self) -> str:
return "original response"
Expand Down
10 changes: 8 additions & 2 deletions testslide/mock_callable.py
Original file line number Diff line number Diff line change
Expand Up @@ -776,8 +776,14 @@ def _patch(
self.type_validation or self.type_validation is None,
)

restore = self._method in self._target.__dict__
restore_value = self._target.__dict__.get(self._method, None)
if isinstance(self._target, (Mock, StrictMock)) or not hasattr(
self._target, "__slots__"
):
restore = self._method in self._target.__dict__
restore_value = self._target.__dict__.get(self._method, None)
else:
restore = self._method in self._target.__slots__
restore_value = getattr(self._target, self._method)

if inspect.isclass(self._target):
new_value = staticmethod(new_value) # type: ignore
Expand Down

0 comments on commit fad7941

Please sign in to comment.