How to create shareable testkit with Junit?

Krzysztof Atłasik :

Let's say I've created a modular project in maven, which has api interface defined in myproject-api, and two implementations of this interface in myproject-impl and myproject-impl2.

myproject-api
myproject-impl
myproject-impl2

I want to create a single test suite, that I could run against both implementations. Of course in the future, I could add another implementation and I would also want to test it using these common tests.

What would be the best practice to achieve that kind of shared tests with junit?

Example of the interface (in myproject-api):

public interface SmallLettersSource {
   String read();
}

Implementations:

  • in module myproject-impl:
class ASource implements SmallLettersSource {

    @Override
    public String read() {
        return "a";
    }
}
  • in module myproject-impl2:
class BSource implements SmallLettersSource {

    @Override
    public String read() {
        return "b";
    }
}

And test (I would also want to add it to myproject-api):

@Test
void test() {
    assert(source.read().equals(source.read().toLowerCase()));
}
Krzysztof Atłasik :

I came up with the following solution:

  1. in myproject-api I created class CommonTestSuite, which is returning list of DynamicTest objects:

    public class CommonTestSuite {
    
        private final Source source;
    
        public CommonTestSuite(Source source) {
             this.source = source;
        }
    
        public Collection<DynamicTest> tests() {
    
            return Arrays.asList(
                dynamicTest("Should return only lowercase.", this::testLowercase),
                dynamicTest("Should return only one letter.", this::testLength)
            );
    
        }
    
        void testLowercase() {
             assert(source.read().equals(source.read().toLowerCase()));
        }
    
        void testLength() {
             assert(source.read().size() == 1);
        }
    }
    
    
    1. Then in tests of my implementation modules, I need only to do:
    class MyProjectImplTest {
    
        @TestFactory
        Collection<DynamicTest> test() {
           return new CommonTestSuite(new ASource()).tests();
        }
    }
    

    and for other modules, I need to do a similar setup. This way I can share common tests between various modules.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=322437&siteId=1