-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Remove myunit #4369
Remove myunit #4369
Conversation
This is excellent! I have a branch that moves several of the assert functions to bare asserts, if that is desired. Also, I believe the original idea was that replacement of the test framework would be concluded when |
@ethanhs thanks! Yeah, maybe "conclude" is not accurate. I hope this PR does not conflict with your branch, it will be very useful. |
@elazarg well, I just checked and it already has quite a few conflicts with master, so this branch can't hurt more than the conflicts that already exist. No worries :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few questions and comments on the changes. Thanks again!
ROADMAP.md
Outdated
@@ -19,9 +19,6 @@ more accurate. | |||
- Continue making error messages more useful and informative. | |||
([issue](https://github.com/python/mypy/labels/topic-usability)) | |||
|
|||
- Switch completely to pytest and remove the custom testing framework. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should keep this until we can run all the tests with just pytest
mypy/test/helpers.py
Outdated
@@ -308,3 +249,52 @@ def retry_on_error(func: Callable[[], Any], max_wait: float = 1.0) -> None: | |||
# Done enough waiting, the error seems persistent. | |||
raise | |||
time.sleep(wait_time) | |||
|
|||
|
|||
class AssertionFailure(Exception): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This Exception and the assert*
s below are the targets I mentioned replacing. They entirely duplicate pytest functionality.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want me to do anything about this in current PR? I wanted to leave these changes to the following PRs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I don't think that is needed.
mypy/test/testargs.py
Outdated
from mypy.main import process_options | ||
|
||
|
||
class ArgSuite(Suite): | ||
def test_coherence(self) -> None: | ||
options = Options() | ||
_, parsed_options = process_options([], require_targets=False) | ||
assert_equal(options, parsed_options) | ||
assert options.__dict__.keys() == parsed_options.__dict__.keys() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you explain why you chose this method of checking equality? assert_equal
is essentially assert not a != b
, I believe this could be a bit different, and is not as straightforward.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added these checks in order to find out why it failed. Since it was helpful for me, I thought it might be better not to switch back.
@@ -67,10 +67,8 @@ def test_interface_subtyping(self) -> None: | |||
self.assert_equivalent(self.fx.f, self.fx.f) | |||
self.assert_not_subtype(self.fx.a, self.fx.f) | |||
|
|||
@skip |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps still leave the TODO item comment here and for the other @skip
s? I sometimes grep for them from time to time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am thinking about skip
as some kind of TODO... I can leave the TODO, but you might want to grep for skips too.
pytest.ini
Outdated
@@ -14,7 +14,7 @@ python_files = test*.py | |||
|
|||
# Because we provide our own collection logic, disable the default | |||
# python collector by giving it empty patterns to search for. | |||
python_classes = | |||
python_classes = *Suite |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps it would be better to explicitly check via e.g. isinstance checks in the custom collector?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The custom collector is for the data-driven tests. It doesn't know about tests derived from TestCase, and I think it might be awkward to make it handle the non-TestCase, non-data-driven tests. I am still thinking about the right way to collect tests, but I prefer to work on it in following PRs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment above this line is no longer up-to-date.
mypy/options.py
Outdated
@@ -129,7 +129,7 @@ def __init__(self) -> None: | |||
self.scripts_are_modules = False | |||
|
|||
# Config file name | |||
self.config_file = None # type: Optional[str] | |||
self.config_file = 'setup.cfg' # type: Optional[str] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this just str
now? (no longer Optional[str]
?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it isn't. Looks like it's possible to have None if there's no config file; but when running the test, there is. I'm not sure about that though; I wonder why ArgSuite doesn't fail on master.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reason for this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change doesn't seem to be related to the rest of PR. Can you remove this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is needed because (as far as I understand) pytest uses the config file, so the default option is not None. I'm not sure this change is the right one; another option I can think of is changing this value inside the test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But this is the mypy config file, which I don't expect to be directly relevant for pytest. Pytest config file should be configured somewhere else (not sure how this works exactly, though) -- and pytest already has a config file (pytest.ini
) which seems to be used. Does this PR do something that requires changes to this? Or maybe I'm talking about a different config file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I might have confused something in my previous response (it's been a while since I tried to figure this out), but note that SHARED_CONFIG_FILES = ('setup.cfg',)
is hardcoded in main.py
. Somewhere in parse_config_file()
there's probably a difference between how myunit and pytest work, so one the former uses None
and the latter uses 'setup.cfg'
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Running myunit, os.path.exists('setup.cfg')
is false. Running pytest, it is true.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm trying a different approach - simply create a new directory and chdir into it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Failed - changing directories did not work on Windows.
I'm not sure why the conflicts don't go away. |
For some reason I've had to fix merge conflicts twice for github to register it. This seems like a bug in Github. I went ahead and did the second merge, things seem to not conflict now. |
This looks pretty reasonable to me. It's always nice when you can delete a lot of code. @JukkaL, is there any reason to not merge this? |
I had look at this a while ago and it looked good, but then I got distracted by fine-grained incremental work and unfortunately didn't finish my review. I'll do another pass this week. Sorry about the slow turnaround -- it will great be to finally drop myunit! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, mostly some minor things. Thanks for the cleanup!
The typeshed change seems unrelated.
mypy/options.py
Outdated
@@ -129,7 +129,7 @@ def __init__(self) -> None: | |||
self.scripts_are_modules = False | |||
|
|||
# Config file name | |||
self.config_file = None # type: Optional[str] | |||
self.config_file = 'setup.cfg' # type: Optional[str] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change doesn't seem to be related to the rest of PR. Can you remove this?
mypy/test/data.py
Outdated
def __init__(self, *, update_data: bool) -> None: | ||
self.update_data = update_data | ||
# Assigned from MypyDataCase.runtest | ||
update_data = False # type: bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style nit: redundant type annotation (you can also remove the str
and bool
annotations above).
mypy/test/helpers.py
Outdated
@@ -312,6 +255,55 @@ def retry_on_error(func: Callable[[], Any], max_wait: float = 1.0) -> None: | |||
time.sleep(wait_time) | |||
|
|||
|
|||
class AssertionFailure(Exception): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could probably use the built-in exception AssertionError
instead of defining a new class here.
mypy/test/helpers.py
Outdated
super().__init__() | ||
|
||
|
||
def assert_true(b: bool, msg: Optional[str] = None) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add comment about assert_true
and assert_false
being redundant (we could just use the assert statement).
from mypy.constraints import SUPERTYPE_OF, SUBTYPE_OF, Constraint | ||
from mypy.solve import solve_constraints | ||
from mypy.test.typefixture import TypeFixture | ||
from mypy.types import Type, TypeVarType, TypeVarId | ||
|
||
|
||
class SolveSuite(Suite): | ||
def __init__(self) -> None: | ||
super().__init__() | ||
def setUp(self) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Elsewhere we had a setup
method, which is a bit confusing. This is needed because of unittest
. I wonder if it make sense to use this name variant uniformly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you insist, but I'm not sure that's desirable. The naming distinction makes it clear where it's required by unittest and where it isn't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok no need to change this. If this becomes a problem we can reconsider.
mypy/test/helpers.py
Outdated
from mypy.myunit import AssertionFailure | ||
|
||
import pytest # type: ignore # no pytest in typeshed | ||
from unittest import TestCase as Suite |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add comment about this, since this may be kind of unexpected. In the future we'd probably want to directly import TestCase
in test files and inherit from it instead of the Suite
alias (and maybe rename some of the other helper classes to avoid ambiguity).
pytest.ini
Outdated
@@ -14,7 +14,7 @@ python_files = test*.py | |||
|
|||
# Because we provide our own collection logic, disable the default | |||
# python collector by giving it empty patterns to search for. | |||
python_classes = | |||
python_classes = *Suite |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment above this line is no longer up-to-date.
* remove redundant type declarartions * comment about aliasing * s/AssertionFailure/AssertionError/g * Fix comment in pytest.ini
a608d48
to
0f3b68e
Compare
0f3b68e
to
a2ebf80
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM now! Thanks for the updates!
Hooray! |
* master: (32 commits) Fix some fine-grained cache/fswatcher problems (python#4560) Sync typeshed (python#4559) Add _cached suffix to test cases in fine-grained tests with cache (python#4558) Add back support for simplified fine-grained logging (python#4557) Type checking of class decorators (python#4544) Sync typeshed (python#4556) When loading from a fine-grained cache, use the real path, not the cached (python#4555) Switch all of the fine-grained debug logging to use manager.log (python#4550) Caching for fine-grained incremental mode (python#4483) Fix --warn-return-any for NotImplemented (python#4545) Remove myunit (python#4369) Store line numbers of imports in the cache metadata (python#4533) README.md: Fix a typo (python#4529) Enable generation and caching of fine-grained dependencies from normal runs (python#4526) Move argument parsing for the fine-grained flag into the main arg parsing code (python#4524) Don't warn about unrecognized options starting with 'x_' (python#4522) stubgen: don't append star arg when args list already has varargs appended (python#4518) Handle TypedDict in diff and deps (python#4510) Fix Options.__repr__ to not infinite recurse (python#4514) Fix some fine-grained incremental bugs with newly imported files (python#4502) ...
These mostly date back to python#4369 There are also some skipped tests in here that fail that I don't touch
These mostly date back to #4369 There are also some skipped tests in here that fail that I don't touch
This should conclude #1673. It uses
unittest.TestCase
as a shortcut, as suggested by @JukkaL. It is aliased asSuite
.The transition is crude, aims at functionality; I intend to clean it up in a later PRs.
myunit.__init__
totest.helpers
. I think some of the asserts should be changed to simpleassert
to take advantage of pytest's introspection.option.py
. I'm not sure why it hadn't fail before.As in previous changes, using
pytest -n0 --collect-only
can give you the list of tests; diffing it with the result of the same command on master shows difference of 155 test items.grep ' def test_' mypy/test/test*.py | wc -l
gives 162 items, and there are 7 skipped items.