mardi 26 avril 2016

Junit test with inheritance, Java right or wrong?

I'm looking for the best way to test different implementations of an interface with as easy and as little code as possible. For this I will use test classes with inheritance.

If you search the web for this, you will find numerous of articles that tells you that this is wrong to include inheritance because it's harder to read and understand and that tests "always" should be one long block of code and it dose not matter if there is a lot of duplicated code. One of the perks of testing this way is that it's easy to test the difference between the implementations with the help of the abstract methods that the testImpls has to implement.

Anyway I would like your opinon on my way to test in this case two different implementations of one interface. The difference between the impls is that ImplCloud puts an package in the cloud while implLocal puts it on disk.

We will have an assert class called SomeImplAsserts and impl Local and Cloud. The test will be constructed with three test classes filled with comments and some pseudo code to explain.

SomeImplAsserts.class ImplCloudTest.class ImplLocalTest.class

public abstract class SomeImplAsserts {
  // Variables that booth implementations need.
  private PathGetter pathGetter;

  // Abstract helper methods. 
  abstract public String getLocalPackagePath(PathGetter pathGetter);

  // Common setup method.
  @Before
  public void setUp() {
  //Setup that's equal for for all impls will be done here.
  }

  @Test
  public void testPackageContent() throws IOException {
  // Place for common assert, asserts where we expect the same value from our implementations will be placed here.

  String pathToPackage = getLocalPackagePath(pathGetter);
  assertEquals("/someTempPath/package.zip", pathToPackage);
  unzip(pathToPackage);

  //asserts on package content.     

  }
  //Common utility methods.
  public void unzip(String abc) throws IOException {
  // unzips the package
  }

  @After
  public void tearDown() {
    //Tear down of all tests will be done here.
  }
}

Impl Cloud:

public class ImplCloudTest extends SomeImplAsserts {

@Override
public String getLocalPackagePath(PathGetter pathGetter) {
  // A place where you could write specific asserts for this impl.
  // This Impl puts an package in the cloud, in order to run tests on the content off the file
  // we would like to put it on disk.

  String url = pathGetter.getPath();
  assertTrue(isUrl(url));

  //Create temp dir and download file to it.

  Path temp = Files.createTempDirectory("someTempPath");
  URI u = URI.create(exportUrl);

  InputStream in = u.toURL().openStream();
  String pathToFile = temp.toString().concat("/" + exportUrl.substring(exportUrl.lastIndexOf("/")));
  Files.copy(in, Paths.get(pathToFile));

  return pathToFile;
}
}

Impl Local:

public class ImplaLocalTest extends SomeImplAsserts {

@Override
public String getLocalPackagePath(PathGetter pathGetter) {
  // this impl puts the file at the disk to begin with. No need to download it.
  String localPath = pathGetter.getPath();
  assertFalse(isUrl(localPath));

  return localPath;
}
}

So what do you think, is this a good way to test different impls or would it be better to simplify it with two to tests with duplicated asserts?

Aucun commentaire:

Enregistrer un commentaire