-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
@Test annotations on interface default methods #1078
Comments
JUnit currently requires JDK5. Most likely, JUnit 5.0 would require JDK 6. We don't want to require more recent JDKs, because many people can't use the latest JDK (including people on Android). Can you do this without default methos? |
|
Not sure if making |
Inheriting from a base abstract works today. It's how I implemented On Sat, Jan 31, 2015 at 10:10 AM, Kevin Cooney notifications@github.com
|
@kcooney The method is run as a test regardless whether it is annotated with |
@josephw Adding |
We'd probably need to scan interfaces for test methods, too. |
Not 100% sure about Java 8's new default methods on interfaces, but the documentation for
See also this SO question. Would be good to verify how default methods are treated. |
Wait, I just realized that you want subclasses to implement the tests, without having to annotate them as a |
In fact,
|
Didn't mean to stir up a hornets nest and I'm not sure of it's implications On Sat, Jan 31, 2015 at 5:15 PM, Stephan Schroevers <
|
Can you provide example code showing what you would want to do? I don't quite see what you would get that you couldn't get with abstract classes or delegation, but I haven't used default methods so I am probably missing something. I don't quite see the use case for having a test class implement multiple interfaces that have default methods annotated with |
Suppose you're code implemented a Comparator of Longs (MyLongComparator), interface ComparatorContract {
assertThat(getComparator().compare(getValue(),getValue())).isEqualTo(0);
getValue()).isLessThan(0);
getLesserValue())).isGreaterThan(0); And then implement tests like: public MyLongComparatorTest implements ComparatorContract { Comparator getComparator() { return new MyLongComparator(); } Long getValue() { return 1L; } Long getLesserValue { return 0L; } } Now this could be done with inheritance, but perhaps you also want to interface NameLengthContract {
} And enhance your test to: public MyLongComparatorTest implements ComparatorContract, Comparator getComparator() { return new MyLongComparator(); } Long getValue() { return 1L; } Long getLesserValue { return 0L; } } With inheritance to achieve this you'd need one test class per contract. On Sat, Jan 31, 2015 at 6:34 PM, Kevin Cooney notifications@github.com
|
Makes sense to me. |
You could do that with @ Inherited annotation because it is Java 5 annotation. The same can be done with @ Ignored. |
@Tibor17, have a look at my comments a bit further up: Can you elaborate on the issues you anticipate with simply modifying |
@Stephan202 |
@Tibor17: I'm afraid we're talking past each other. I did not mean to say that JUnit currently doesn't use |
@Stephan202 |
We are currently working on a plan to have a JUnit extension/version for Java 8. This would be a good fit! |
If we support |
Nice. When it's testable I'll jump on it. On Sun, Feb 15, 2015 at 3:17 AM, Marc Philipp notifications@github.com
|
I'd like this implemented, too, because that would make reusing tests much easier. My interface hierarchy is quite convoluted (a geometry library), so each class must be tested for compliance to the contracts of its interface tree. In the current state of JUnit, I can create abstract classes that contain tests for interfaces, and inherit those classes each time an implementation implements an interface, but it causes a lot of boilerplate code anyway. If I could add test methods as mixins, there would be zero boilerplate in my tests. |
@Suseika having a test implement multiple interfaces with default methods can have some of the same problems as multiple inheritance. I wonder if we can find other ways to solve your problem. I suggest starting a thread that describes your problem either on the mailing list or on StackOverflow.com and adding a link to the thread here. |
+1 |
@test might be interesting in JUnit 4.x because the super method can be reused in parameterized test, but in JUni 5.x I guess we can resolve this issue and problem around inheritance by
Till now the class was only an umbrella for us and mostly not inherited. As an alternative concept
The JUnitCore will use
No @test annotation, no class, only multiple interface inheritance. |
Default interface methods as tests expands the ability to express complex test matrices, which is why I went ahead and did #1222. Theories have limitations in their ability to express complex fixture construction, and have an awkward tooling story. Parameterised tests are difficult to extend. Abstract tests are limited to a linear hierarchy. Allowing default interface methods as tests would pretty much lift the linear hierarchy restriction of the abstract test pattern. I don't know @Suseika particular use case, but geometry sounds like a domain where this would be useful. Java8 has already decided how name clashes should be handled. If a class gets default methods with the same signature from two different interfaces, then that method gets re-abstracted and the concrete implementing class has to implement the method and resolve the conflict that way. When it comes to tests, and you have a name conflict in default methods, you can either rename one of the tests if thats in your power, or you can implement the test method to call the test methods from both interfaces, or create two new test methods call the respective methods on the interfaces. For example, if the interfaces public class MyTest implements A, B {
@Override
public void tt() {
A.super.tt();
B.super.tt();
}
} Or like this: public class MyTest implements A, B {
@Override
public void tt() {
}
@Test
public void ttA() {
A.super.tt();
}
@Test
public void ttB() {
B.super.tt();
}
} However, I think that this will not be a very common problem. Tests usually have long and descriptive names, so I suspect that name conflicts are rare. The use case that drove me to write a pull request for this feature is the following: I am implementing my own page cache, which does off-heap caching of file data, and therefore has to interface with file systems. To speed things up, I do most of my testing on an in-memory file system, but it is also important that I run my tests on a real file system, since the in-memory implementation might not be a faithful substitute. Further more, I also want to run my tests in a mode where the real file system is doing fault-injection in a different way than usual. The API for my page cache is described and specified in interfaces, and most of the tests are written in terms of those APIs, which means they are decoupled from the implementation. So far, this gives me the following abstract test hierarchy:
This works, but I suffer from some of the tests being slow – even when run with the in-memory file system. So I'd like to extract those into
I could alternatively have a separate hierarchy for the slow tests, and this is actually what I currently do, but it means that I have to duplicate the set-up for making the tests use the real file system, and likewise for the fault injection in the real file system. That's why I desire this feature. |
@marcphilipp is right. The inheritance is for classes. |
Our new prototype "JUnit Lambda" supports all annotations ( Please take a look here: |
I vote to close this, since JUnit lambda does this. |
JUnit 5 supports writing tests as interface default methods: Therefore, I close this issue. |
I was hoping to make and interface with @test annotated default methods that my tests could implement. Didn't appear to see these tests.
The text was updated successfully, but these errors were encountered: