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