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