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

cloudinit: move to pytest for running tests #211

Merged
merged 3 commits into from Mar 10, 2020
Merged

cloudinit: move to pytest for running tests #211

merged 3 commits into from Mar 10, 2020

Conversation

OddBloke
Copy link
Collaborator

@OddBloke OddBloke commented Feb 13, 2020

As the nose docs[0] themselves note, it has been in maintenance mode for the past several years. pytest is an actively developed, featureful and popular alternative that the nose docs themselves recommend. See [1] for more details about the thinking here.

(This PR also removes stale tox definitions, instead of modifying them.)

[0] https://nose.readthedocs.io/en/latest/
[1] https://lists.launchpad.net/cloud-init/msg00245.html

@OddBloke OddBloke added the wip Work in progress, do not land label Feb 13, 2020
@github-actions github-actions bot added the CLA signed The submitter of the PR has signed the CLA label Feb 13, 2020
@smoser
Copy link
Collaborator

smoser commented Feb 14, 2020

Is there a reason you pushed this branch to canonical/cloud-init rather than oddbloke's fork?
I'd suggest that best practice would be to not have push access to the repo, or at very least for your development system to use the read-only for the upstream remote.

Copy link
Collaborator

@smoser smoser left a comment

Choose a reason for hiding this comment

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

It feels like you need some changes to packages/pkg-deps.json which might fall out if you try to use tools/run-container.

tox.ini Outdated
@@ -65,7 +64,7 @@ commands =
[testenv:xenial]
commands =
python ./tools/pipremove jsonschema
python -m nose {posargs:tests/unittests cloudinit}
py.test {posargs:tests/unittests cloudinit}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I did a quick test, and 'python -m pytest' works here.
That would mean we should be able to use a consistent 'commands' line of:

{envpython} -m pytest ....

tox.ini Outdated
--cover-inclusive --cover-package=cloudinit \
commands = pytest \
--durations 10 \
{posargs:--cov cloudinit --cov-branch \
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you change this to --cov=cloudinit ? It makes it obvious that cloud-init is a value to the --cov key, rather than some other thing.

@OddBloke
Copy link
Collaborator Author

OddBloke commented Feb 14, 2020 via email

@OddBloke
Copy link
Collaborator Author

OddBloke commented Feb 14, 2020 via email

@OddBloke OddBloke force-pushed the pytest branch 2 times, most recently from 0dfa394 to ad07235 Compare February 14, 2020 19:20
@@ -48,10 +46,10 @@ pyflakes3:
@$(CWD)/tools/run-pyflakes3

unittest: clean_pyc
nosetests $(noseopts) tests/unittests cloudinit
python -m pytest -v tests/unittests cloudinit
Copy link
Contributor

Choose a reason for hiding this comment

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

Given that we are dropping Python 2 support with 20.1 release, I think the unittest target should be dropped rather than changing it.

tox.ini Outdated
@@ -45,7 +44,7 @@ deps = -r{toxinidir}/test-requirements.txt

[testenv:py26]
deps = -r{toxinidir}/test-requirements.txt
commands = nosetests {posargs:tests/unittests cloudinit}
commands = {envpython} -m pytest {posargs:tests/unittests cloudinit}
Copy link
Contributor

Choose a reason for hiding this comment

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

Rather than making changes we should drop the sections for Py versions we no longer want to support.

@OddBloke
Copy link
Collaborator Author

OddBloke commented Feb 18, 2020 via email

@OddBloke OddBloke force-pushed the pytest branch 2 times, most recently from e8effdd to d694bee Compare February 18, 2020 17:58
Copy link
Collaborator

@blackboxsw blackboxsw left a comment

Choose a reason for hiding this comment

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

Generally I'm +1 on this, but when running tox -e xenial pytest in a python 3.7 environment the pytest run is failing for me on tox -e xenial target with 126 test errors due to python 3.7 raising StopIteration exceptions as RuntimeErrors.

We might have to find the right pinned version of pytest for the xenial tox env?

py3 env works fine with: pytest 5.3.5
xenial though doesn't have StopIteration exception handling support in pytest 2.8.7
I think we might need to specify pytest==3.0.7. As that version seems to have the fix needed https://docs.pytest.org/en/latest/changelog.html#id980

_______________ ERROR collecting cloudinit/tests/test_version.py _______________
.tox/xenial/lib/python3.7/site-packages/_pytest/runner.py:149: in __init__
    self.result = func()
.tox/xenial/lib/python3.7/site-packages/_pytest/main.py:431: in _memocollect
    return self._memoizedcall('_collected', lambda: list(self.collect()))
.tox/xenial/lib/python3.7/site-packages/_pytest/main.py:311: in _memoizedcall
    res = function()
.tox/xenial/lib/python3.7/site-packages/_pytest/main.py:431: in <lambda>
    return self._memoizedcall('_collected', lambda: list(self.collect()))
.tox/xenial/lib/python3.7/site-packages/_pytest/python.py:604: in collect
    return super(Module, self).collect()
.tox/xenial/lib/python3.7/site-packages/_pytest/python.py:458: in collect
    res = self.makeitem(name, obj)
.tox/xenial/lib/python3.7/site-packages/_pytest/python.py:470: in makeitem
    collector=self, name=name, obj=obj)
.tox/xenial/lib/python3.7/site-packages/_pytest/vendored_packages/pluggy.py:724: in __call__
    return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
.tox/xenial/lib/python3.7/site-packages/_pytest/vendored_packages/pluggy.py:338: in _hookexec
    return self._inner_hookexec(hook, methods, kwargs)
.tox/xenial/lib/python3.7/site-packages/_pytest/vendored_packages/pluggy.py:333: in <lambda>
    _MultiCall(methods, kwargs, hook.spec_opts).execute()
.tox/xenial/lib/python3.7/site-packages/_pytest/vendored_packages/pluggy.py:595: in execute
    return _wrapped_call(hook_impl.function(*args), self.execute)
.tox/xenial/lib/python3.7/site-packages/_pytest/vendored_packages/pluggy.py:249: in _wrapped_call
    wrap_controller.send(call_outcome)
E   RuntimeError: generator raised StopIteration

I think we may have to sort

tox.ini Outdated
@@ -83,39 +76,10 @@ deps =
# test-requirements
httpretty==0.9.6
mock==1.3.0
nose==1.3.7
pytest==2.8.7
Copy link
Collaborator

Choose a reason for hiding this comment

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

Xenial is busted for me: I think we need 3.0.7

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We don't need or want 3.0.7, because that's not the version in xenial:

$ rmadison python-pytest
...
 python-pytest | 2.8.7-4        | xenial/universe         | all
...

The problem here is that, not especially surprisingly, the version of pytest in xenial doesn't work with a more recent version of Python. pytest 2.8.7 does work fine on xenial's version of Python, because we have this tox target in our Travis configuration, and the build is green for this PR: https://travis-ci.org/canonical/cloud-init/jobs/652102211

I think the "fix" here is to accept that we can no longer run the xenial tox env on focal. (This case has always been of limited utility because unless you're running xenial, you aren't actually testing a configuration that we ever expect to be deployed; no-one is running xenial's libraries with Python 3.8 in the real world.) As such, I don't think this is a great loss. I'll push up a change to the default tox targets that we run.

Does that sound OK?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Your argument above I think boils down to "Distro x has a different version of python than the developer's system. Therefore test of distro x in tox is of no use.". Taken to its limits, the argument basically defeats the entire intent of tox. Tox does not reproduce exactly the target of any environment, but usefully and easily approximates them.

The xenial tox environment was never a perfect environment. But it caught a very large number of errors that would only otherwise be exposed in much heavier test environment (a container or package build).

The value provided was less about testing a specific python but more about testing dependencies at the levels specified. Ie we have restricted our use of requests to version 2.9.1. If you used some feature of requests not present in that version, then test would fail. Tox did a good job of quickly finding failure where we used feature or behavior of a library at one version that was not available at a different version.

I don't have a good answer. But just dropping the environment will result in a higher number of developer failures being found by c-i that previously were found on developers run of 'tox'.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

OK, I've just pushed up 8affaf2 which addresses this much better, I think. (For some reason, the PR hasn't updated, GitHub is having some Issues.)

@OddBloke
Copy link
Collaborator Author

OddBloke commented Feb 25, 2020 via email

@smoser
Copy link
Collaborator

smoser commented Feb 25, 2020

My concern is that if we relax the pytest requirement here, so that
things pass on development machines, then CI will no longer catch use of
pytest features (or the existence of pytest bugs) which will cause
package builds to fail. I'll spend a bit of time thinking about how we
could work around this.

I had assumed or implied that there was CI running that would test in an
actual xenial environment (run-container?) and would report failure.
I think that is a requirement either way. If you do not have that,
and xenial is removed from the default tox environment, then we're
basically guaranteed to see failure at daily-build-recipe time ...
way after the thing is merged.

Is there something that will run tests in xenial environment?

@OddBloke
Copy link
Collaborator Author

OddBloke commented Feb 25, 2020 via email

tox.ini Show resolved Hide resolved
Copy link
Collaborator

@smoser smoser left a comment

Choose a reason for hiding this comment

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

i'm good with this at this point.
Thank you, Daniel.

Copy link
Collaborator

@blackboxsw blackboxsw left a comment

Choose a reason for hiding this comment

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

Thanks for the followup @OddBloke the xenial-dev makes a lot more sense to me.
I'm +1 on this, but I think we need to discuss when this needs to land as we have 2 FFes queued and potntially another bug-fix new-upstream-snapshot to handle as well during Ubuntu Focal feature freeze.

I want to make sure we are doing the least amount of cherry picking we can.

@OddBloke OddBloke removed the wip Work in progress, do not land label Mar 10, 2020
Daniel Watkins and others added 3 commits March 10, 2020 10:22
As the nose docs[0] themselves note, it has been in maintenance mode for
the past several years.  pytest is an actively developed, featureful and
popular alternative that the nose docs themselves recommend.

[0] https://nose.readthedocs.io/en/latest/
Instead of updating them for pytest without testing.
This environment is identical to [testenv:xenial], but uses the earliest
version of pytest that works with Python 3.8.
@blackboxsw
Copy link
Collaborator

The cloud-init project already has tooling to handle cherry-picks into specific Ubuntu series, so we decided we shouldn't be blocking landing any PRs in master due to external Ubuntu feature freeze constraints. As such, we can land this approved branch and upstream will sort Ubuntu-specific cherry-picks required during feature freeze.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA signed The submitter of the PR has signed the CLA
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants