BaseTestHelper.java

  1. /*
  2.  * *********************************************************************************************************************
  3.  *
  4.  * TheseFoolishThings: Miscellaneous utilities
  5.  * http://tidalwave.it/projects/thesefoolishthings
  6.  *
  7.  * Copyright (C) 2009 - 2023 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. 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.  * 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.      ******************************************************************************************************************/
  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.      ******************************************************************************************************************/
  79.     @Nonnull
  80.     public String readStringFromResource (@Nonnull final String resourceName)
  81.             throws IOException
  82.       {
  83.         final var file = resourceFileFor(resourceName);
  84.         final var buffer = new StringBuilder();
  85.         var separator = "";

  86.         for (final var string : Files.readAllLines(file, UTF_8))
  87.           {
  88.             buffer.append(separator).append(string);
  89.             separator = "\n";
  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.      ******************************************************************************************************************/
  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.     @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.                     Paths.get("target/test-classes", testClass.getSimpleName(), "expected-results", resourceName);

  131.             if (Files.exists(expectedFile))
  132.               {
  133.                 return expectedFile;
  134.               }
  135.           }

  136.         throw new FileNotFoundException("Expected file for test " + resourceName);
  137.       }

  138.     /*******************************************************************************************************************
  139.      *
  140.      * A manipulator of a pair of (actual file, expected file).
  141.      *
  142.      ******************************************************************************************************************/
  143.     @RequiredArgsConstructor(access = PRIVATE)
  144.     public final class TestResource
  145.       {
  146.         @Nonnull
  147.         private final String name;

  148.         @Nonnull
  149.         private final Path actualFile;

  150.         @Nonnull
  151.         private final Path expectedFile;

  152.         /***************************************************************************************************************
  153.          *
  154.          * Assert that the content of the actual file are the same as the expected file.
  155.          *
  156.          * @throws IOException     in case of error
  157.          *
  158.          **************************************************************************************************************/
  159.         public void assertActualFileContentSameAsExpected ()
  160.                 throws IOException
  161.           {
  162.             assertSameContents(expectedFile.toFile(), actualFile.toFile());
  163.           }

  164.         /***************************************************************************************************************
  165.          *
  166.          * Writes the given strings to the actual file.
  167.          *
  168.          * @param   strings         the strings
  169.          * @throws IOException     in case of error
  170.          *
  171.          **************************************************************************************************************/
  172.         public void writeToActualFile (@Nonnull final String... strings)
  173.                 throws IOException
  174.           {
  175.             writeToActualFile(List.of(strings));
  176.           }

  177.         /***************************************************************************************************************
  178.          *
  179.          * Writes the given strings to the actual file.
  180.          *
  181.          * @param   strings         the strings
  182.          * @throws IOException     in case of error
  183.          *
  184.          **************************************************************************************************************/
  185.         public void writeToActualFile (@Nonnull final Iterable<String> strings)
  186.                 throws IOException
  187.           {
  188.             Files.write(actualFile, strings, UTF_8);
  189.           }

  190.         /***************************************************************************************************************
  191.          *
  192.          * Writes the given bytes to the actual file.
  193.          *
  194.          * @param   bytes           the bytes
  195.          * @throws IOException     in case of error
  196.          *
  197.          **************************************************************************************************************/
  198.         public void writeToActualFile (@Nonnull final byte[] bytes)
  199.                 throws IOException
  200.           {
  201.             Files.write(actualFile, bytes);
  202.           }

  203.         /***************************************************************************************************************
  204.          *
  205.          * Reads the content from the resource file as a single string.
  206.          *
  207.          * @return the string
  208.          * @throws IOException     in case of error
  209.          *
  210.          **************************************************************************************************************/
  211.         @Nonnull
  212.         public String readStringFromResource ()
  213.                 throws IOException
  214.           {
  215.             return BaseTestHelper.this.readStringFromResource(name);
  216.           }
  217.       }
  218.   }