-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Move testparse to pytest #3780
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
Move testparse to pytest #3780
Conversation
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 seems to work, but I don't know this code very well -- do you understand it well enough to confidently say this is right?
mypy/test/data.py
Outdated
@@ -556,6 +556,9 @@ def repr_failure(self, excinfo: Any) -> str: | |||
|
|||
|
|||
class DataSuite: | |||
def __init__(self, *, update_data: bool = False) -> 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.
Since you're adding this here you should update all the classes that derive from it. Or you can follow the existing pattern and leave it out here but add such a __init__
method to ParserSuite
(like all other subclasses of DataSuite
do). It seems these classes all need an update_date
keyword argument because of the call on line 533 in data.py (line number from master, it's in runtest()
in MypyDataCase
).
Note that these classes don't seem to be instantiated anywhere, I suppose they are recognized dynamically. Do you know how?
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 it here since I believe that at the end of the road no class will need it, or any other argument. So for the time being, a prototype __init__
in the base class (just for that keyword) should suffice.
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.
These classes are gathered by pytest, passed to as the obj
argument to pytest_pycollect_makeitem
which returns a MypyDataSuite
wrapping this obj
. Later the collect
method is called on the MypyDataSuite
instance, and our implementation iterates over self.obj.cases()
, wrapping and yielding the results.
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.
Yeah, that explanation of how they are called makes sense.
I still think that now you're adding __init__
to DataSuite
, all subclasses of it that also define __init__
should be modified to call super().__init__(update_data=update_data)
. Otherwise my spider-sense about inheritance is unhappy.
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 only class that actually defines a nontrivial __init__
is ASTMergeSuite
(and I'm not sure it should, since it does not receive arguments and does not seem to have any mutable state).
May I simply remove the empty __init__
definitions?
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 you should remove those __init__
definitions that are now a copy of DataSuite.__init__
, and make the others call super().__init__(update_data=update_data)
. I think there may be one or two that ignore their update_data
argument, please figure out if those simply don't need it or if setting it would just be ignored.
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.
Currently the only test that uses this option is testcheck
, which uses update_testcase_output
if it's set. The others simply ignore it.
parse_files = ['parse.test', | ||
'parse-python2.test'] | ||
|
||
def cases(self) -> List[DataDrivenTestCase]: | ||
@classmethod |
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.
Does it actually matter whether this is a class method or an instance method? (I don't know -- can you tell me?)
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's called without an instance (line 515 in data.py, obj is the class itself); it could have been a static method. Better yet, it could not exist at all, since the needed information here is only the file names and 2-3 options.
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.
For now it has to be a classmethod since it's this is how it's declared in DataSuite.
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.
Oh, I think I realize what confused me. There's a class Suite
with a cases()
instance method, and a class DataSuite
with a cases()` class method. The two are not directly related (though I suspect that some duck typing may still be going on). Anyway, no need to change this back. :-)
I don't know if that would help the review in any way, but here is an almost-complete migration of everything to pytest, plus making individual tests run in 0.5s instead of 4. It's "almost", and it's one huge step, and it's outdated. So I'm trying* to do it step by step. * (I really am :) ) |
Maybe there's a way to automate testing-the-tests to avoid regression. As a sanity check I randomly put errors in the tests and watch them fail. This is not systematic enough though. |
Also, running
gives a list of collected tests:
|
@@ -35,9 +35,6 @@ | |||
|
|||
|
|||
class FineGrainedSuite(DataSuite): | |||
def __init__(self, *, update_data: bool) -> None: | |||
pass | |||
|
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.
Or did you want here a call to super().__init__
?
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'll merge once the tests pass. Thanks for your patience!
Ok. If everything goes well, please let me know how do you want to continue. There are 3 more data-driven test (testtransform, testtypegen, testsemanal), all of them are similarly straightforward. Do you want a dedicated PR for each of them or a single one? |
Thanks! I much prefer to review smaller pieces (easier to get them done between meetings :-). |
Thanks for doing this @elazarg! I will be so happy once we can fully switch to pytest. |
IIUC, this is an item from #1673. I tried to keep this minimal.
(If this goes well I can add more)