简体   繁体   中英

Providing tests as part of a library

Suppose an interface like:

public interface Fooer {
  void foo();
  boolean isFooed();
}

This is part of a Java library that I'm writing. Users of this library are supposed to implement this interface and pass objects into my library.

I want to provide a way for users to test their implementation to hold the invariants my library code assumes.

Following the above example:

Fooer f = getUsersFooer();
f.foo();
// f.isFooed() MUST return true now

Is it possible, and if so, feasible or even acceptable to provide such tests as part of the library?

(I don't know whether these would be considered unit tests or integration tests... they test the modifications made by a single method using getter methods or very primitive non-mutating methods)

Sure, I can write classes like

public class TestFooer {
  public static boolean test(Fooer f) {
    // ...
  }
}

but is there a "standard way", using the usual testing frameworks (JUnit, ...)?

It's a common pattern used to check the compliance of implementations of some spec. This is called a TCK, Technology Compatibility Kit . I've not looked at the code of many TCKs, but I've seen them often using TestNG .

There was a recent addition to JUnit 5.8.0-M1 that allows to define test suites that can be used for this, too.

Your TCK has a non-test dependency on your API and org.junit.jupiter:junit-jupiter (at least 5.8.0-M1 ) plus org.junit.platform:junit-platform-suite (at least 1.8.0-M1 ). The tests are not in src/test/java but src/main/java . Then you add a suite class to your TCK like:

package org.example;

import org.junit.platform.suite.api.SelectPackages;
import org.junit.platform.suite.api.Suite;

@Suite
@SelectPackages("org.example")
public abstract class TestCompatibilityKitSuite {}

Note that this class doesn't have to be abstract, I just think it makes the intended usage more clear.

The implementation then has a dependency on the api and a test dependency on the tck . To run the tests, add a class like:

package test;

import org.example.TestCompatibilityKitSuite;

class TckTest extends TestCompatibilityKitSuite {}

The TCK has to load the implementation. A good way to do so is by using a java.util.ServiceLoader . For a full example look here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM