ApprovalTests.Java icon indicating copy to clipboard operation
ApprovalTests.Java copied to clipboard

Provide custom ApprovalNamer for unknown class names

Open beatngu13 opened this issue 5 years ago • 5 comments

If I have understood correctly, Approvals uses AttributeStackSelector to determine the file name at runtime, but it is currently only aware of the following class names:

  • org.testng.annotations.Test
  • org.junit.Test
  • org.junit.jupiter.api.Test

Is there a way to provide a custom ApprovalNamer for unknown class names? Just like #36, which mentions issues with e.g. @ParameterizedTest in this comment, I get the same exception for @RepeatedTest.

I guess there are many situations where the user wants to use Approvals inside a method with an unknown annotation/class name. Therefore, I think it would be helpful to have a way to provide a custom ApprovalNamer, something like:

Approvals.verify( new MyApprovalNamer(), object );

Or a global property. Is there anything like this already possible or planned? If not, I can submit a corresponding PR if anyone is interested.

beatngu13 avatar Jun 06 '19 07:06 beatngu13

I'd be interested in something like this for use with Groovy & Spock. @beatngu13 do you already have a working approach?

dpost avatar Sep 04 '19 20:09 dpost

@dpost we currently use our own ApprovalsUtil on top of ApprovalTests, which sets the paths as we want them. The internal ApprovalTests call looks as follows:

Approvals.verify( new ApprovalTextWriter( actual, fileExtensionWithoutDot ),
        new MavenConformJUnitStackTraceNamer(),
        DiffReporter.INSTANCE );

Where:

public class MavenConformJUnitStackTraceNamer implements ApprovalNamer {

	private final StackTraceReflectionResult info;

	public MavenConformJUnitStackTraceNamer() {
		info = TestUtils.getCurrentFileForMethod( new JUnitStackSelector() );
	}

	@Override
	public String getApprovalName() {
		return String.format( "%s.%s", info.getClassName(), info.getMethodName() );
	}

	@Override
	public String getSourceFilePath() {
		final String pathPrefix = separator + "src" + separator + "test" + separator;
		final String srcTestJavaPath = pathPrefix + "java";
		final String srcTestResourcesPath = pathPrefix + "resources";
		final String testClassPath = info.getSourceFile().getAbsolutePath();
		return (testClassPath + separator).replace( srcTestJavaPath, srcTestResourcesPath );
	}
}

I'm sure it is possible less verbose, but it does the job and puts the golden master files in src/test/resources/... instead of beside the test class.

However, it would be cool if ApprovalTests would provide an easier API for this. So, if anyone shares this desire, I'd be happy to help.

beatngu13 avatar Sep 09 '19 16:09 beatngu13

we believe this is fixed in v8.0.0

LarsEckart avatar Jun 22 '20 22:06 LarsEckart

@LarsEckart thx for the update! Would you mind pointing to the corresponding documentation? Looking forward to try it out (and close the issue).

beatngu13 avatar Jun 23 '20 06:06 beatngu13

hello @beatngu13 ,

I'm sorry but it looks like I mixed up the issues last night. What we fixed was the exception which is thrown for ParameterizedTests (issue #36 ).

Regarding the better API for custom names, we just yesterday briefly talked about adding support for Options, and I think that sounds like something that might fit under that topic.

LarsEckart avatar Jun 23 '20 10:06 LarsEckart