avh4 / imagecomparison

Tools for comparing images and writing image-based approval tests. This library is published on Maven Central.
8 stars 4 forks source link

Add non package/method name paths #6

Open Shryne opened 5 years ago

Shryne commented 5 years ago

Currently, I am using the looksLike matcher to compare images. The problem is that the matcher takes the package name of the caller and uses it to build the path to the image. This way, I must use the matcher directly in my tests and nowhere else.
In my case, I want to use the matcher to create my own. Unfortunately, the looksLike matcher takes the package name of the matcher instead of the actual test method.

Is it possible to change the path/get rid of the "package to path" including feature? And if yes, it would be nice if this would be mentioned in the readme file.

avh4 commented 5 years ago

It looks like you can call looksLike with a second parameter, which is any class, and I believe it will use the package name of that given class to generate the path to the image file.
https://github.com/avh4/imagecomparison/blob/bc6353fcf2e01e836478c0bd282c1817c0051a23/imagecomparison/src/main/java/net/avh4/util/imagecomparison/hamcrest/ImageComparisonMatchers.java#L31-L32 (When you call looksLike without the second argument, it just tries to guess the class name that you're calling from by inspecting the call stack, and then uses the class it guesses to fill in the second argument).

I haven't been doing any Java programing in a few years, so if you have an update to the documentation, feel free to make a PR for that.

avh4 commented 5 years ago

I think maybe you could also use the matchesFile matcher if you want complete control over specifying the name of the image file. https://github.com/avh4/imagecomparison/blob/bc6353fcf2e01e836478c0bd282c1817c0051a23/imagecomparison/src/main/java/net/avh4/util/imagecomparison/hamcrest/ImageComparisonMatchers.java#L63

Shryne commented 5 years ago

Using the class argument of looksLike, I managed to solve the problem in my matcher. I just copied your code into my matcher to get the caller and put this argument into the looksLike matcher:

final Class<?> clazz;
try {
  clazz = Class.forName(
    StackUtils
      .getCallingTestMethodStackTraceElement()
      .getClassName()
  );
} catch (final ClassNotFoundException exception) {
  throw new IllegalStateException(
    "Couldn't get the class object of the caller.",
    exception
  );
}
try {
  return ImageComparisonMatchers.looksLike(path, clazz);
} catch (final IOException exception) {
  throw new IllegalStateException(
    "The path to the image seems to be wrong.", exception
  );
}

Unfortunately, that means that my matcher can't be used to build another matcher without using the same code to get the caller.

I tried to use matchesFile and it seems like it's purpose is to check whether a file has the expected string-based content. The code of the method supports this assumption.

I guess it's really a lack of a base method, where one has to specify the exact path to the image file. When I find some time, I will try to add such a method.