Skip to content

Commit

Permalink
First stab at switching to pytest, including pytest tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
bitprophet committed May 9, 2017
1 parent caccb2e commit 876d0f3
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 33 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
build
.coverage
htmlcov
.cache
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ matrix:
install:
- pip install -r dev-requirements.txt
script:
- TERM=xterm-256color inv test
- inv test
# I have this in my git pre-push hook, but contributors probably don't
- flake8
9 changes: 5 additions & 4 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
# Dev version of Invoke
invoke>=0.13.0,<2.0
# Self, for runtime/task dependencies
-e .
# For packaging
wheel==0.24
twine==1.5
# For testing
nose==1.3.0
spec>=1.4.0,<2.0
pytest-relaxed>=0.1.0,<2
pytest-cov==2.4.0
mock==1.0.1
watchdog==0.8.3
coverage==3.7.1
# For linting
flake8==2.4.0

# Self, for runtime/task dependencies
-e .
51 changes: 51 additions & 0 deletions invocations/pytest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""
Pytest-using variant of testing.py. Will eventually replace the latter.
"""

from invoke import Collection, task


@task
def test(c, verbose=True, color=True, capture='sys', opts=''):
"""
Run pytest with given options.
:param bool verbose:
Whether to run tests in verbose mode.
:param bool color:
Whether to request colorized output (typically only works when
``verbose=True``.)
:param str capture:
What type of stdout/err capturing pytest should use. Defaults to
``sys`` since pytest's own default, ``fd``, tends to trip up
subprocesses trying to detect PTY status. Can be set to ``no`` for no
capturing / useful print-debugging / etc.
:param str opts:
Extra runtime options to hand to ``pytest``.
"""
# TODO: really need better tooling around these patterns
# TODO: especially the problem of wanting to be configurable, but
# sometimes wanting to override one's config via kwargs; and also needing
# non-None defaults in the kwargs to inform the parser (or have to
# configure it explicitly...?)
flags = []
if verbose:
flags.append('--verbose')
if color:
flags.append('--color=yes')
flags.append('--capture={}'.format(capture))
if opts is not None:
flags.append(opts)
c.run("pytest {}".format(" ".join(flags)), pty=True)


@task
def coverage(c):
"""
Run pytest with coverage enabled.
Assumes the ``pytest-cov`` pytest plugin is installed.
"""
4 changes: 4 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ universal = 1
exclude = .git,build,dist
ignore = E124,E125,E128,E261,E301,E302,E303
max-line-length = 79

[tool:pytest]
testpaths = tests
python_files = *
26 changes: 9 additions & 17 deletions tasks.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,20 @@
from invoke import Collection, task

from invocations.packaging import release
from invocations.testing import test, watch_tests, coverage as coverage_
from invocations import pytest as pytests


# TODO: add coverage at the Travis level as well sometime. For now this is just
# to help me as I overhaul the release modules

@task
def coverage(c, html=True):
# TODO: can we realistically make use of functools.partial for this sort of
# thing?
# TODO: is it best left to config option overrides (currently the usual
# approach)? Is there stuff we can do to make that even easier?
return coverage_(c, html=html, integration_=False)


ns = Collection(release, test, watch_tests, coverage)
ns = Collection(release, pytests.test, pytests.coverage)
ns.configure({
'tests': {
'package': 'invocations',
},
'packaging': {
'sign': True,
'wheel': True,
},
'run': {
'env': {
# Our ANSI color tests test against hardcoded codes appropriate for
# this terminal, for now.
'TERM': 'xterm-256color',
},
},
})
2 changes: 1 addition & 1 deletion tests/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from invocations.console import confirm


class confirm_(Spec):
class confirm_:
@patch('invocations.console.input', return_value='yes')
def displays_question_with_yes_no_suffix(self, mock_input):
confirm("Are you sure?")
Expand Down
25 changes: 15 additions & 10 deletions tests/packaging/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
from invoke.vendor.lexicon import Lexicon

from mock import Mock, patch
from spec import Spec, trap, skip, eq_, ok_, raises
# TODO: trap might work as-is but should still be migrated into pytest-relaxed
# (or find/use existing pytest functionality for same)
from spec import trap, skip, eq_, ok_, raises

from invocations.packaging.semantic_version_monkey import Version

Expand All @@ -22,7 +24,7 @@
)


class release_line_(Spec):
class release_line_:
def assumes_bugfix_if_release_branch(self):
c = MockContext(run=Result("2.7"))
eq_(release_line(c)[1], Release.BUGFIX)
Expand All @@ -42,7 +44,7 @@ def is_undefined_if_specific_commit_checkout(self):
eq_(release_line(c)[1], Release.UNDEFINED)


class latest_feature_bucket_(Spec):
class latest_feature_bucket_:
def base_case_of_single_release_family(self):
eq_(
latest_feature_bucket(dict.fromkeys(['unreleased_1_feature'])),
Expand Down Expand Up @@ -74,7 +76,7 @@ def ordering_goes_by_numeric_not_lexical_order(self):
)


class release_and_issues_(Spec):
class release_and_issues_:
class bugfix:
# TODO: factor out into setup() so each test has some excluded/ignored
# data in it - helps avoid naive implementation returning x[0] etc.
Expand Down Expand Up @@ -116,7 +118,7 @@ def undefined_always_returns_None_and_empty_list(self):
skip()


class find_package_(Spec):
class find_package_:
def can_be_short_circuited_with_config_value(self):
# TODO: should we just bundle this + the version part into one
# function and setting? do we ever peep into the package for anything
Expand All @@ -137,7 +139,7 @@ def errors_if_ambiguous_results(self):
skip()


class load_version_(Spec):
class load_version_:
def setup(self):
sys.path.insert(0, support_dir)

Expand Down Expand Up @@ -167,7 +169,7 @@ def errors_usefully_if_version_module_not_found(self):
skip()


class latest_and_next_version_(Spec):
class latest_and_next_version_:
def next_patch_of_bugfix_release(self):
eq_(
latest_and_next_version(Lexicon({
Expand Down Expand Up @@ -313,7 +315,7 @@ def _expect_actions(self, *actions):
)


class status_(Spec):
class status_:
class overall_behavior:
_branch = '1.1'
_changelog = 'unreleased_1.1_bugs'
Expand Down Expand Up @@ -370,6 +372,9 @@ def returns_lexica_for_reuse(self):
eq_(found_state.latest_version, Version('1.1.1'))
eq_(found_state.tags, [Version(x) for x in self._tags])

# TODO: I got this attribute jazz working in pytest but see if there is a
# 'native' pytest feature that works better (while still in conjunction
# with nested tasks, ideally)
class release_line_branch:
_branch = '1.1'

Expand Down Expand Up @@ -572,7 +577,7 @@ def _run_all(c, mute=True):
raise


class All(Spec):
class All:
"all_" # mehhh

# NOTE: just testing the base case of 'everything needs updating',
Expand Down Expand Up @@ -700,7 +705,7 @@ def no_changelog_update_needed_means_no_changelog_edit(self, _):
# TODO: yes, when I personally went from TERM=xterm-256color to
# TERM=screen-256color, that made these tests break! Updating test machinery to
# account for now, but...not ideal!
class component_state_enums_contain_human_readable_values(Spec):
class component_state_enums_contain_human_readable_values:
class changelog:
def okay(self):
eq_(
Expand Down

0 comments on commit 876d0f3

Please sign in to comment.