apache / apache/grails-core

feature request and quick fix: provide an extension point for customizing the file name

Open
#14,329 9 comments 0 reactions 0 assignees View on GitHub
relates-to: grails-geb
Dominant language
Groovy
Stars
2.9k
Forks
975
Avg merge
1d 22h
Merged PRs (30d)
92

Description

> Regarding the file names, feel free to create an issue or open a PR.
> We should be able to improve the handling or provide an extension point for customizing the file name generation.

_Originally posted by @matrei in [#128](https://github.com/grails/geb/issues/128#issuecomment-2622057330)_

Creating this issue to provide other people searching for it with a solution until I or more knowledgeful people come up with a paradigm of how it should be implemented since GebConfig.groovy is no longer used and the @ContainerGebConfig.groovy does not seem right

* Create a File [`src/integration-test/resources/SpockConfig.groovy`](https://spockframework.org/spock/docs/2.2/data_driven_testing.html#_configuration) with

```groovy
unroll {
includeFeatureNameForIterations false
defaultPattern "#iterationIndex"
}
```

results in e.g. : `Screen recordings for test DemoSpec_upload_files_to_existing_object_0 will be stored at: build/gebContainer/recordings/20250207_123726/FAILED-DemoSpec_upload_files_to_existing_object_0-20250207-123845.mp4` , which is 115 characters, resulting in absolute path length of 189 in my local folder structure

instead of: `Screen recordings for test DemoCRUDSpec_upload_files_to_existing_object_upload_files_to_existing_object_appendShippingNote_false_appendInvoice_false_shippingNoteExtract_Lieferschein_invoiceExtract_Rechnungsnr_shippingDisplay_LS67949_invoiceDisplay_RG67229_0_ will be stored at: build/gebContainer/recordings/20250207_124010/FAILED-DemoCRUDSpec_upload_files_to_existing_object_upload_files_to_existing_object_appendShippingNote_false_appendInvoice_false_shippingNoteExtract_Lieferschein_invoiceExtract_Rechnungsnr_shippingDisplay_LS67949_invoiceDisplay_RG67229_0_-20250207-124121.mp4`

Stacktrace for SEO:

```
Suppressed: java.nio.file.FileSystemException: build/gebContainer/recordings/20250207_124010/FAILED-DemoCRUDSpec_upload_files_to_existing_object_upload_files_to_existing_object_appendShippingNote_false_appendInvoice_false_shippingNoteExtract_Lieferschein_invoiceExtract_Rechnungsnr_shippingDisplay_LS67949_invoiceDisplay_RG67229_0_-20250207-124121.mp4: File name too long
at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:100)
at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116)
at java.base/sun.nio.fs.UnixFileSystemProvider.implDelete(UnixFileSystemProvider.java:249)
at java.base/sun.nio.fs.AbstractFileSystemProvider.deleteIfExists(AbstractFileSystemProvider.java:110)
at java.base/java.nio.file.Files.deleteIfExists(Files.java:1181)
at java.base/java.nio.file.Files.copy(Files.java:3055)
at org.testcontainers.containers.VncRecordingContainer.saveRecordingToFile(VncRecordingContainer.java:129)
at org.testcontainers.containers.BrowserWebDriverContainer.retainRecordingIfNeeded(BrowserWebDriverContainer.java:396)
at org.testcontainers.containers.BrowserWebDriverContainer.afterTest(BrowserWebDriverContainer.java:347)
at grails.plugin.geb.GebRecordingTestListener.afterIteration(GebRecordingTestListener.groovy:46)
at org.spockframework.runtime.MasterRunListener.afterIteration(MasterRunListener.java:50)
at org.spockframework.runtime.MasterRunSupervisor.afterIteration(MasterRunSupervisor.java:118)
at org.spockframework.runtime.PlatformSpecRunner.runIteration(PlatformSpecRunner.java:219)
at org.spockframework.runtime.IterationNode.around(IterationNode.java:63)
at org.spockframework.runtime.IterationNode.around(IterationNode.java:11)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.NodeTestTask$DefaultDynamicTestExecutor.execute(NodeTestTask.java:226)
at org.junit.platform.engine.support.hierarchical.NodeTestTask$DefaultDynamicTestExecutor.execute(NodeTestTask.java:204)
at org.spockframework.runtime.ParameterizedFeatureChildExecutor.execute(ParameterizedFeatureChildExecutor.java:53)
at org.spockframework.runtime.PlatformParameterizedSpecRunner.runIterations(PlatformParameterizedSpecRunner.java:187)
at org.spockframework.runtime.PlatformParameterizedSpecRunner.runParameterizedFeature(PlatformParameterizedSpecRunner.java:45)
at org.spockframework.runtime.ParameterizedFeatureNode.execute(ParameterizedFeatureNode.java:40)
at org.spockframework.runtime.ParameterizedFeatureNode.execute(ParameterizedFeatureNode.java:16)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.spockframework.runtime.SpockNode.sneakyInvoke(SpockNode.java:40)
at org.spockframework.runtime.FeatureNode.lambda$around$0(FeatureNode.java:29)
at org.spockframework.runtime.PlatformSpecRunner.lambda$createMethodInfoForDoRunFeature$4(PlatformSpecRunner.java:199)
at org.spockframework.runtime.model.MethodInfo.invoke(MethodInfo.java:148)
at org.spockframework.runtime.PlatformSpecRunner.invokeRaw(PlatformSpecRunner.java:407)
at org.spockframework.runtime.PlatformSpecRunner.invoke(PlatformSpecRunner.java:390)
at org.spockframework.runtime.PlatformSpecRunner.runFeature(PlatformSpecRunner.java:192)
at org.spockframework.runtime.FeatureNode.around(FeatureNode.java:29)
at org.spockframework.runtime.FeatureNode.around(FeatureNode.java:8)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.spockframework.runtime.SpockNode.sneakyInvoke(SpockNode.java:40)
at org.spockframework.runtime.SpecNode.lambda$around$0(SpecNode.java:63)
at org.spockframework.runtime.PlatformSpecRunner.lambda$createMethodInfoForDoRunSpec$0(PlatformSpecRunner.java:61)
at org.spockframework.runtime.model.MethodInfo.invoke(MethodInfo.java:148)
at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:102)
at grails.plugin.geb.GrailsContainerGebExtension$_visitSpec_closure4.doCall(GrailsContainerGebExtension.groovy:98)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:107)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:274)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1035)
at groovy.lang.Closure.call(Closure.java:412)
at org.codehaus.groovy.runtime.ConvertedClosure.invokeCustom(ConvertedClosure.java:50)
at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:112)
at com.sun.proxy.$Proxy56.intercept(Unknown Source)
at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:101)
at org.spockframework.runtime.PlatformSpecRunner.invoke(PlatformSpecRunner.java:398)
at org.spockframework.runtime.PlatformSpecRunner.runSpec(PlatformSpecRunner.java:55)
at org.spockframework.runtime.SpecNode.around(SpecNode.java:63)
at org.spockframework.runtime.SpecNode.around(SpecNode.java:11)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:62)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at com.sun.proxy.$Proxy5.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
```

Contributor guide

Open the contributing guide

Research direction

Start with the reported SpockConfig.groovy workaround, then inspect GebRecordingTestListener.groovy at line 46 and GrailsContainerGebExtension.groovy at line 98, where the stack trace reaches the recording flow. Clarify the intended extension point and configuration approach; done should allow customized recording names without triggering the reported File name too long failure.

Written by the indexing model from the issue text.

Assessment

Tech stack
groovy
Domain
testing
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.