org.netbeans.jellytools.JellyTestCase Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.netbeans.jellytools;
import java.awt.Component;
import java.awt.Window;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.swing.JDialog;
import javax.swing.SwingUtilities;
import junit.framework.AssertionFailedError;
import org.netbeans.jemmy.ComponentChooser;
import org.netbeans.jemmy.DialogWaiter;
import org.netbeans.jemmy.EventTool;
import org.netbeans.jemmy.JemmyException;
import org.netbeans.jemmy.JemmyProperties;
import org.netbeans.jemmy.TestOut;
import org.netbeans.jemmy.operators.JDialogOperator;
import org.netbeans.jemmy.util.Dumper;
import org.netbeans.jemmy.util.PNGEncoder;
import org.netbeans.junit.AssertionFailedErrorException;
import org.netbeans.junit.NbModuleSuite;
import org.netbeans.junit.NbTestCase;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.Exceptions;
/** JUnit test case with implemented Jemmy/JellyTools support stuff.
*
* @author Adam Sotona
*/
public class JellyTestCase extends NbTestCase {
/** screen capture feature in case of failure is enabled by default
*/
public boolean captureScreen = Boolean.valueOf(System.getProperty("jemmy.screen.capture", "true")).booleanValue();
/** screen XML dump feature in case of failure is disabled by default
*/
public boolean dumpScreen = Boolean.getBoolean("jemmy.screen.xmldump");
/** closing all modal dialogs after each test case is disabled by default
*/
public boolean closeAllModal = Boolean.valueOf(System.getProperty("jelly.close.modal", "true")).booleanValue();
/** Wait 1000 ms before every test case */
public boolean waitNoEvent = Boolean.valueOf(System.getProperty("jelly.wait.no.event", "true")).booleanValue();
/** constructor required by JUnit
* @param testName method name to be used as testcase
*/
public JellyTestCase(String testName) {
super(testName);
}
/** Inits environment before test case is executed. It can be overridden
* in sub class but it is recommended to call super.initEnvironment() at
* the beginning.
*
* Default initialization: output messages from jemmy are redirected
* to jemmy.log file in workdir; jemmy timeouts are loaded from
* org.netbeans.jellytools.timeouts and if system property jelly.timeouts_resource
* or jelly.timeouts_file are set, timeouts are loaded from specified
* resource/file;
*/
protected void initEnvironment() {
// redirect log messages from jemmy to jemmy.log file in workdir
PrintStream jemmyLog = getLog("jemmy.log");
JemmyProperties.setCurrentOutput(new TestOut(System.in, jemmyLog, jemmyLog));
// load timeouts
String timeoutsResource = System.getProperty("jelly.timeouts_resource");
String timeoutsFile = System.getProperty("jelly.timeouts_file");
try {
JemmyProperties.getCurrentTimeouts().load(getClass().getClassLoader().
getResourceAsStream("org/netbeans/jellytools/timeouts"));
if (timeoutsResource != null && !"".equals(timeoutsResource)) {
JemmyProperties.getCurrentTimeouts().load(
getClass().getClassLoader().getResourceAsStream(timeoutsResource));
} else if (timeoutsFile != null && !"".equals(timeoutsFile)) {
JemmyProperties.getCurrentTimeouts().load(timeoutsFile);
}
} catch (Exception e) {
throw new JemmyException("Initialization of timeouts failed.", e);
}
}
/** Overridden method from JUnit framework execution to perform conditional
* screen shot and conversion from TimeoutExpiredException to AssertionFailedError.
* Waits a second before test execution.
* @throws Throwable Throwable
*/
@Override
public void runBare() throws Throwable {
initEnvironment();
// wait
if (waitNoEvent) {
new EventTool().waitNoEvent(1000);
}
try {
super.runBare();
} catch (ThreadDeath td) {
// ThreadDead must be re-throwed immediately
throw td;
} catch (Throwable th) {
// suite is notified about test failure so it can do some debug actions
try {
failNotify(th);
} catch (Exception e3) {
}
captureScreen();
// closes all modal dialogs in dependency on systems property
if (closeAllModal) {
try {
closeAllModal();
} catch (Exception e) {
}
}
if (th instanceof JemmyException) {
// all instancies of JemmyException are re-throwed as AssertionError (test failed)
throw new AssertionFailedErrorException(th.getMessage(), th);
} else {
throw th;
}
}
}
/**
* Ensures that screen capture is done before the tearDown() is called
* @throws java.lang.Throwable
*/
@Override
protected void runTest() throws Throwable {
try {
super.runTest();
} catch (ThreadDeath td) {
// ThreadDead must be re-throwed immediately
throw td;
} catch (Throwable th) {
captureScreen();
throw th;
}
}
private boolean isScreenCaptured = false;
private void captureScreen() {
if (!isScreenCaptured) {
// screen capture is performed when test fails and in dependency on system property
if (captureScreen) {
try {
String captureFile = getWorkDir().getAbsolutePath() + File.separator + "screen.png";
PNGEncoder.captureScreen(captureFile, PNGEncoder.COLOR_MODE);
noteCaptureFile(captureFile);
} catch (Exception ex) {
ex.printStackTrace(getLog());
}
}
// send thread dump to log
PrintStream w = getLog();
w.println("thread dump just after screen capture:");
w.println(threadDump());
// XML dump is performed when test fails and in dependency on system property
if (dumpScreen) {
try {
String captureFile = getWorkDir().getAbsolutePath() + File.separator + "screen.xml";
Dumper.dumpAll(captureFile);
noteCaptureFile(captureFile);
} catch (Exception ex) {
ex.printStackTrace(getLog());
}
}
isScreenCaptured = true;
}
}
/**
* If running inside Hudson, print a message to make it easy to see where the capture file might be archived.
*/
private void noteCaptureFile(String captureFile) {
String hudsonURL = System.getenv("HUDSON_URL");
if (hudsonURL == null) {
return;
}
String workspace = System.getenv("WORKSPACE");
if (!workspace.endsWith(File.separator)) {
workspace += File.separator;
}
if (!captureFile.startsWith(workspace)) {
return;
}
String relCaptureFile = captureFile.substring(workspace.length()).replace(File.separatorChar, '/');
System.err.println("Capturing to:");
System.err.println(hudsonURL + "job/" + System.getenv("JOB_NAME") + "/"
+ System.getenv("BUILD_NUMBER") + "/artifact/" + relCaptureFile);
}
/** Method called in case of fail or error just after screen shot and XML dumps.
* Override this method when you need to be notified about test failures or errors
* but avoid any exception to be throwed from this method.
* super.failNotify() does not need to be called because it is empty.
* @param reason Throwable reason of current fail */
protected void failNotify(Throwable reason) {
}
/** Closes all opened modal dialogs. Non-modal stay opened. */
public static void closeAllModal() {
JDialog dialog;
ComponentChooser chooser = new ComponentChooser() {
@Override
public boolean checkComponent(Component comp) {
return (comp instanceof JDialog
&& comp.isShowing()
&& ((JDialog) comp).isModal());
}
@Override
public String getDescription() {
return ("Modal dialog");
}
};
while ((dialog = (JDialog) DialogWaiter.getDialog(chooser)) != null) {
closeDialogs(findBottomDialog(dialog, chooser), chooser);
}
}
private static JDialog findBottomDialog(JDialog dialog, ComponentChooser chooser) {
Window owner = dialog.getOwner();
if (chooser.checkComponent(owner)) {
return (findBottomDialog((JDialog) owner, chooser));
}
return (dialog);
}
private static void closeDialogs(JDialog dialog, ComponentChooser chooser) {
Window[] ownees = dialog.getOwnedWindows();
for (int i = 0; i < ownees.length; i++) {
if (chooser.checkComponent(ownees[i])) {
closeDialogs((JDialog) ownees[i], chooser);
}
}
new JDialogOperator(dialog).requestClose();
}
/** Finishes test with status Fail
* @param t Throwable reason of test failure
*/
public void fail(Throwable t) {
t.printStackTrace(getLog());
throw new AssertionFailedErrorException(t);
}
/*
* methods for managing failures of group of dependent tests
* Usage: each method involved in a group must start with
* startTest() call and when finished it must perform endTest().
* To clear the test status (new group of tests does not depend on
* previous tests), method must call clearTestStatus() prior to startTest()
* Example:
* public void myTest() {
* startTest();
* // do my stuff
* endTest();
* }
*/
/** private variable for holding state whether test was finished
*/
private boolean testStatus = true;
/** Checks whether previous test finished correctly and
* sets test status to 'not finished' state
*
*/
protected void startTest() {
if (!testStatus) {
fail("Depending on previous test, but it failed");
}
testStatus = false;
}
/** Sets the test status to 'finished' state (test passed)
*/
protected void endTest() {
testStatus = true;
}
/** Clears test status (used when test does not depend on previous test)
*/
protected void clearTestStatus() {
testStatus = true;
}
private List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy