Skip to content

Method: testResourceFor(String)

1: /*
2: * *************************************************************************************************************************************************************
3: *
4: * TheseFoolishThings: Miscellaneous utilities
5: * http://tidalwave.it/projects/thesefoolishthings
6: *
7: * Copyright (C) 2009 - 2025 by Tidalwave s.a.s. (http://tidalwave.it)
8: *
9: * *************************************************************************************************************************************************************
10: *
11: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
12: * You may obtain a copy of the License at
13: *
14: * http://www.apache.org/licenses/LICENSE-2.0
15: *
16: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
17: * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
18: *
19: * *************************************************************************************************************************************************************
20: *
21: * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
22: * git clone https://github.com/tidalwave-it/thesefoolishthings-src
23: *
24: * *************************************************************************************************************************************************************
25: */
26: package it.tidalwave.util.test;
27:
28: import jakarta.annotation.Nonnull;
29: import java.util.List;
30: import java.io.FileNotFoundException;
31: import java.io.IOException;
32: import java.nio.file.Files;
33: import java.nio.file.Path;
34: import lombok.RequiredArgsConstructor;
35: import lombok.extern.slf4j.Slf4j;
36: import static java.nio.charset.StandardCharsets.UTF_8;
37: import static it.tidalwave.util.test.FileComparisonUtils.assertSameContents;
38: import static lombok.AccessLevel.PRIVATE;
39:
40: /***************************************************************************************************************************************************************
41: *
42: * A facility that provides some common tasks for testing, such as manipulating test files.
43: *
44: * @author Fabrizio Giudici
45: * @since 3.2-ALPHA-18
46: *
47: **************************************************************************************************************************************************************/
48: @RequiredArgsConstructor @Slf4j
49: public class BaseTestHelper
50: {
51: @Nonnull
52: protected final Object test;
53:
54: /***********************************************************************************************************************************************************
55: * Returns a {@link Path} for a resource file. The resource should be placed under
56: * {@code src/test/resources/test-class-simple-name/test-resources/resource-name}. Note that the file actually
57: * loaded is the one under {@code target/test-classes} copied there (and eventually filtered) by Maven.
58: *
59: * @param resourceName the resource name
60: * @return the {@code Path}
61: **********************************************************************************************************************************************************/
62: @Nonnull
63: public Path resourceFileFor (@Nonnull final String resourceName)
64: {
65: final var testName = test.getClass().getSimpleName();
66: return Path.of("target/test-classes", testName, "test-resources", resourceName);
67: }
68:
69: /***********************************************************************************************************************************************************
70: * Reads the content from the resource file as a single string. See {@link #resourceFileFor(String)} for
71: * further info.
72: *
73: * @param resourceName the resource name
74: * @return the string
75: * @throws IOException in case of error
76: **********************************************************************************************************************************************************/
77: @Nonnull
78: public String readStringFromResource (@Nonnull final String resourceName)
79: throws IOException
80: {
81: final var file = resourceFileFor(resourceName);
82: final var buffer = new StringBuilder();
83: var separator = "";
84:
85: for (final var string : Files.readAllLines(file, UTF_8))
86: {
87: buffer.append(separator).append(string);
88: separator = "\n";
89: }
90:
91: return buffer.toString();
92: // return String.join("\n", Files.readAllLines(path, UTF_8)); TODO JDK 8
93: }
94:
95: /***********************************************************************************************************************************************************
96: * Create a {@link TestResource} for the given name. The actual file will be created under
97: * {@code target/test-artifacts/test-class-simple-name/resourceName}. The expected file should be
98: * placed in {@code src/test/resources/test-class-simple-name/expected-results/resource-name}. Note that the file
99: * actually loaded is the one under {@code target/test-classes} copied there (and eventually filtered) by Maven.
100: * The {@code test-class-simple-name} is tried first with the current test, and then with its eventual
101: * super-classes; this allows to extend existing test suites. Note that if the resource files for a super class are
102: * not in the current project module, they should be explicitly copied here (for instance, by means of the
103: * Maven dependency plugin).
104: *
105: * @param resourceName the name
106: * @return the {@code TestResource}
107: * @throws IOException in case of error
108: **********************************************************************************************************************************************************/
109: @Nonnull
110: public TestResource testResourceFor (@Nonnull final String resourceName)
111: throws IOException
112: {
113: final var testName = test.getClass().getSimpleName();
114: final var expectedFile = findExpectedFilePath(resourceName);
115: final var actualFile = Path.of("target/test-artifacts", testName, resourceName);
116: Files.createDirectories(actualFile.getParent());
117: return new TestResource(resourceName, actualFile, expectedFile);
118: }
119:
120: /***********************************************************************************************************************************************************
121: *
122: **********************************************************************************************************************************************************/
123: @Nonnull
124: private Path findExpectedFilePath (@Nonnull final String resourceName)
125: throws IOException
126: {
127: for (var testClass = test.getClass(); testClass != null; testClass = testClass.getSuperclass())
128: {
129: final var expectedFile =
130: Path.of("target/test-classes", testClass.getSimpleName(), "expected-results", resourceName);
131:
132: if (Files.exists(expectedFile))
133: {
134: return expectedFile;
135: }
136: }
137:
138: throw new FileNotFoundException("Expected file for test " + resourceName);
139: }
140:
141: /***********************************************************************************************************************************************************
142: * A manipulator of a pair of (actual file, expected file).
143: **********************************************************************************************************************************************************/
144: @RequiredArgsConstructor(access = PRIVATE)
145: public final class TestResource
146: {
147: @Nonnull
148: private final String name;
149:
150: @Nonnull
151: private final Path actualFile;
152:
153: @Nonnull
154: private final Path expectedFile;
155:
156: /***************************************************************************************************************
157: *
158: * Assert that the content of the actual file are the same as the expected file.
159: *
160: * @throws IOException in case of error
161: *
162: **************************************************************************************************************/
163: public void assertActualFileContentSameAsExpected ()
164: throws IOException
165: {
166: assertSameContents(expectedFile.toFile(), actualFile.toFile());
167: }
168:
169: /***************************************************************************************************************
170: *
171: * Writes the given strings to the actual file.
172: *
173: * @param strings the strings
174: * @throws IOException in case of error
175: *
176: **************************************************************************************************************/
177: public void writeToActualFile (@Nonnull final String... strings)
178: throws IOException
179: {
180: writeToActualFile(List.of(strings));
181: }
182:
183: /***************************************************************************************************************
184: *
185: * Writes the given strings to the actual file.
186: *
187: * @param strings the strings
188: * @throws IOException in case of error
189: *
190: **************************************************************************************************************/
191: public void writeToActualFile (@Nonnull final Iterable<String> strings)
192: throws IOException
193: {
194: Files.write(actualFile, strings, UTF_8);
195: }
196:
197: /***************************************************************************************************************
198: *
199: * Writes the given bytes to the actual file.
200: *
201: * @param bytes the bytes
202: * @throws IOException in case of error
203: *
204: **************************************************************************************************************/
205: public void writeToActualFile (@Nonnull final byte[] bytes)
206: throws IOException
207: {
208: Files.write(actualFile, bytes);
209: }
210:
211: /***************************************************************************************************************
212: *
213: * Reads the content from the resource file as a single string.
214: *
215: * @return the string
216: * @throws IOException in case of error
217: *
218: **************************************************************************************************************/
219: @Nonnull
220: public String readStringFromResource ()
221: throws IOException
222: {
223: return BaseTestHelper.this.readStringFromResource(name);
224: }
225: }
226: }