-
Notifications
You must be signed in to change notification settings - Fork 246
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
Abstract test case #166
Comments
The most common way of doing this I have seen is, use your first approach, but put the abstract Another solution is to leverage the Does this help? |
For a commonly reused base class, moving to another module makes sense. More often I'm creating a base local to my test, though, and need to share asserts or tests; like panhania, creating a mixin by omitting the proper base class bothers me. I've previously had the idea to have a e.g. |
The "ignore abstract classes" approach works because A decorator e.g. |
FR in stdlib from many years ago: https://bugs.python.org/issue17519#msg388510 |
Oh I misunderstood #166 (comment), if it means to skip all abstract classes by inspecting it in the test loader like https://bugs.python.org/issue17519#msg184959 suggests (as opposed to define a |
Yes: I want a feature that does this, but no: I think abstract classes do not successfully implement what we need. I think that using Consider where we get the test loader to ignore any class for which
But then consider these two failure cases:
In this example, having the metaclass set up for AbstractTestCase doesn't have any effect, because an abstract class without any abstract methods is not abstract. So any testcases defined will run, setUp will run etc. There is a second failure case, where we accidentally skip concrete classes. Consider what happens if you add a second abstract method (or misspell a method name!)
Because FooTest doesn't implement 'bar' it will be silently skipped. The tests will 'pass', your unit tests are green, and everything's fine. This ends up being unintended action-at-a-distance. Typically abstract classes raise an exception when they're created in case-2 to tell you you've done it wrong, but when the test loader skips abstract classes, you don't get that safety. I have an alternate approach I've prototyped for absl, which is to instead add a new decorator, |
Sometimes we have some interface and we would like to write a generic test suite for it, so that concrete implementations just reuse it.
The problem with Python's
unittest
(and transitivelyabsltest
) is that theTestCase
class serves as a "marker" telling the test executor that it should be executed. This is unfortunate, because abstract test suites should not run. Consider this example:Here, the test executor will instantiate
FooTest
,QuuxTest
andNorfTest
. However,FooTest
is abstract and it is not possible to create an instance of it. There are three workarounds for this that I am aware of.The first one is to configure the test executor to ignore specific test classes or prefixes (possible in pytest). However, this is awkward and requires modifying external configuration files.
The second one is described here. Basically, we
del
the base class once child classes are defined. This feels very wrong and works only if all the concrete test cases are defined in the same module.The last one is to use a mixin approach. Instead of making
FooTest
derive fromabsltest.TestCase
, we "mark" only concrete classes with it:The problem here is that it doesn't work with static type checkers:
FooTest
now doesn't inherit fromTestCase
but uses methods likeself.assertEqual
.This last solution seems like the only "correct" one except for the mentioned issue. Instead, Abseil could define an abstract test class and make the normal test case class implement it:
Then, it would be possible to inherit from
absltest.AbstractTestCase
in the abstract test case, making the type checker happy:The text was updated successfully, but these errors were encountered: