feature request and quick fix: provide an extension point for customizing the file name
- 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
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