All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.anrisoftware.globalpom.utils.TestUtils.groovy Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2011-2025 Erwin Müller 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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 CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.anrisoftware.globalpom.utils

import java.nio.charset.Charset

import org.apache.commons.io.Charsets
import org.apache.commons.io.FileUtils
import org.apache.commons.io.IOUtils
import org.apache.commons.lang3.SerializationUtils
import org.apache.commons.lang3.StringUtils
import org.apache.commons.lang3.builder.ToStringBuilder
import org.apache.commons.lang3.builder.ToStringStyle
import org.joda.time.Duration
import org.joda.time.ReadableDuration
import org.slf4j.Logger
import org.slf4j.LoggerFactory

import name.fraser.neil.plaintext.diff_match_patch

/**
 * Various utilities to simplify the groovy tests.
 *
 * @author Erwin Mueller, [email protected]
 * @since 1.5
 */
class TestUtils {

	private final static Logger LOG = LoggerFactory.getLogger(TestUtils)

	/**
	 * Set default to-string style.
	 */
	public static toStringStyle = ToStringBuilder.setDefaultStyle(ToStringStyle.SHORT_PREFIX_STYLE)

	/**
	 * Default epsilon for the equality of two values.
	 */
	static epsilon = 10**-16

	/**
	 * The initial delay before the first action, in milliseconds.
	 *
	 * @see #sequencedActions(Object)
	 */
	static long startDelay = 2000

	/**
	 * The last delay after the actions are executed, in milliseconds.
	 *
	 * @see #sequencedActions(Object)
	 */
	static long endDelay = 2000

	/**
	 * The delay before each action is executed, in milliseconds.
	 *
	 * @see #sequencedActions(Object)
	 */
	static long actionDelay = 1000

	/**
	 * The default {@link Charset} for the tests.
	 *
	 * @since 1.10
	 */
	static Charset charset = Charsets.UTF_8

	/**
	 * Flag if the strings should be trimmed before comparison.
	 * Default is set to {@code false} which
	 * means no trimming is done. See {@link String#trim()}.
	 *
	 * @since 1.11
	 */
	static boolean trimStrings = false

	/**
	 * Flag if the line ending should be ignored before comparison of
	 * strings. Default is set to {@code true} which
	 * means the line ending is ignored.
	 * 

* On different systems the line ending can be different: Windows is using * {@code \n\r} and Linux is using {@code \n}. If this flag is set to * {@code true} the line ending will be treated the same. * * @since 1.11 */ static boolean normalizeLineEnding = true /** * Reads the resource with the specified name and specified character set, * relative to the context class. * * @param resource * the URL of the resource. * * @return the content of the resource. * * @since 1.10 */ static String resourceToString(URL resource) { IOUtils.toString resource, charset } /** * Copy the resource to a target file and make the file executable. * Create any parent directories of the target. * * @since 1.10 */ static void copyResourceToCommand(URL resource, File target) { FileUtils.copyURLToFile resource, target target.setExecutable true, false } /** * Create a temporary file with an optional content. * * @param text * the text context of the file. Default is empty string. * * @return the temporary {@link File}. * * @since 1.10 */ static File createTempFile(String text="") { def tmpFile = File.createTempFile(this.getClass().name, null) FileUtils.write tmpFile, text, charset tmpFile.deleteOnExit() return tmpFile } /** * Assert that the file content equals the given string. If not we create * a difference patch of the string and the file content. * * @param file * the {@link File} that content is read. * * @param expected * the expected resource {@link URL}, {@link File} or object. * The resource URL or file is read. If it's neither a * resource URL nor a file then the object is interpreted * as a string. * * @since 1.11 */ static void assertFileContent(File file, def expected) { String fileString = fileToString(file) String string if (expected instanceof URL) { string = resourceToString((URL) expected) } else if (expected instanceof File) { string = fileToString((File) expected) } else { string = expected.toString() } assertStringContent(fileString, string) } /** * Assert that one string equals a different string. If not we create * a difference patch of the string and the file content. The file content is trimmed before * comparison, according to {@link #trimStrings}. * * @param string * the test string. * * @param expected * the expected string. * * @since 1.11 */ static void assertStringContent(String string, String expected) { if (trimStrings) { expected = expected.trim() string = string.trim() } if (normalizeLineEnding) { string = StringUtils.replace(string, "\r\n", "\n") string = StringUtils.replace(string, "\r", "\n") expected = StringUtils.replace(expected, "\r\n", "\n") expected = StringUtils.replace(expected, "\r", "\n") } if (string != expected) { def log = LoggerFactory.getLogger(TestUtils) def diffMatch = new diff_match_patch() def patch = diffMatch.patch_make string, expected def diff = diffMatch.patch_toText patch log.error "String A: \n>>>\n{}<<>>\n{}<< assert (it - b[idx]).abs() < epsilon : "The difference between $a and $b is greater than $epsilon" } } /** * Starts the executions of actions after an initial delay. The actions are * delayed for a fixed amount of time. At the end we have again a delay. *

* The method is good for actions that the user have to see to verify, like * GUI actions. *

* Example with only the initial and end delay: *

	 * sequencedActions { }
	 * 
* Example with only one action: *
	 * sequencedActions { model.addElement "Ddd" }
	 * 
* Example to execute different GUI related actions: *
	 * sequencedActions(
	 * 		{ childrenPanel.name = name },
	 * 		{ model.addElement "Ddd" },
	 * 		{ model.addElement "Eee" },
	 * 		{ model.addElement "Fff" }
	 * )
	 * 
* * * @param actions * a list of actions. The first actions is the initial action and is * executed after the startDelay delay. Subsequent actions * are executed after the fixed delay specified in * actionDelay. After the last action the delay * endDelay is waited. * * @param arg * the argument that is passed to each action. * * @see #startDelay * @see #endDelay * @see #actionDelay * * @since 1.10 */ static void sequencedActions(Object... actions) { sequencedActionsWith(null, actions) } /** * Starts the executions of actions after an initial delay. The actions are * delayed for a fixed amount of time. At the end we have again a delay. *

* The method is good for actions that the user have to see to verify, like * GUI actions. *

* Example with only the initial and end delay: *

	 * sequencedActionsWith foo, { }
	 * 
* Example with only one action: *
	 * sequencedActions foo, { model.addElement "Ddd" }
	 * 
* Example to execute different GUI related actions: *
	 * sequencedActions(foo,
	 * 		{ childrenPanel.name = name },
	 * 		{ model.addElement "Ddd" },
	 * 		{ model.addElement "Eee" },
	 * 		{ model.addElement "Fff" }
	 * )
	 * 
* * * @param actions * a list of actions. The first actions is the initial action and is * executed after the startDelay delay. Subsequent actions * are executed after the fixed delay specified in * actionDelay. After the last action the delay * endDelay is waited. * * @param arg * the argument that is passed to each action. * * @see #startDelay * @see #endDelay * @see #actionDelay * * @since 1.13 */ static void sequencedActionsWith(def arg, Object... actions) { Thread.sleep startDelay actions.first()(arg) actions.drop(1).each { Thread.sleep actionDelay it(arg) } Thread.sleep endDelay } /** * Waits for a condition to be true and asserts that the time it took is * less then the specified timeout duration. * *
	 * waitFor { condition == true }
	 * 
* * @param condition * the condition for that we wait for. * * @param timeout * the {@link ReadableDuration} duration for the timeout. * Defaults to 25 seconds. * * @since 1.13 */ static void waitFor(def condition, ReadableDuration timeout = Duration.parse("PT25S")) { long time = System.currentTimeMillis() long timeNow = time while (!condition() && timeNow - time < timeout.millis) { Thread.sleep 100 timeNow = System.currentTimeMillis() } assert timeNow - time <= timeout.millis } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy