Skip to content

Commit

Permalink
Simple GUI Test
Browse files Browse the repository at this point in the history
Integration tests are now separated from the normal unit tests and have to be called manually.
  • Loading branch information
simonharrer committed Jan 31, 2016
1 parent 7d66412 commit 2cef1fe
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 62 deletions.
8 changes: 7 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@ sudo: false
before_install:
- chmod +x gradlew

# allow gui testing on travis
before_script:
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
- sleep 3 # give xvfb some time to start

script:
- ./gradlew test --info
- ./gradlew test testIntegration --info

# cache gradle dependencies
cache:
Expand Down
21 changes: 21 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ repositories {
configurations {
antlr3
antlr4

integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
}

dependencies {
Expand Down Expand Up @@ -100,6 +103,7 @@ dependencies {

testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:1.10.19'
integrationTestCompile 'org.assertj:assertj-swing-junit:3.0.2'

compile 'org.jsoup:jsoup:1.8.3'
compile 'com.mashape.unirest:unirest-java:1.4.7'
Expand All @@ -115,6 +119,14 @@ sourceSets {
srcDirs = ["src/main/java", "src/main/gen"]
}
}
integrationTest {
java {
compileClasspath += main.output + test.output
runtimeClasspath += main.output + test.output
srcDir file('src/integration-test/java')
}
resources.srcDir file('src/integration-test/resources')
}
}

processResources {
Expand Down Expand Up @@ -204,6 +216,15 @@ test {
}
}

task integrationTest(type: Test) {
testClassesDir = sourceSets.integrationTest.output.classesDir
classpath = sourceSets.integrationTest.runtimeClasspath
}

tasks.withType(Test) {
reports.html.destination = file("${reporting.baseDir}/${name}")
}

jacocoTestReport {
reports {
xml.enabled = true // coveralls plugin depends on xml format report
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package net.sf.jabref.gui;

import junit.framework.AssertionFailedError;
import org.junit.Assert;

import javax.swing.*;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
* Can catch any exceptions occuring on the EDT thread for assertion.
*/
public class AWTExceptionHandler {

private final List<Throwable> list = new CopyOnWriteArrayList<>();

public void installExceptionDetectionInEDT() {
SwingUtilities.invokeLater(() -> Thread.currentThread().setUncaughtExceptionHandler((t, e) -> list.add(e)));
}

public void assertNoExceptions() {
if(!list.isEmpty()) {
throw new AssertionError("Uncaught exception in EDT", list.get(0));
}
}

}
104 changes: 104 additions & 0 deletions src/integration-test/java/net/sf/jabref/gui/GUITest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package net.sf.jabref.gui;

import net.sf.jabref.JabRefMain;
import net.sf.jabref.gui.preftabs.PreferencesDialog;
import org.assertj.swing.core.GenericTypeMatcher;
import org.assertj.swing.dependency.jsr305.Nonnull;
import org.assertj.swing.fixture.FrameFixture;
import org.assertj.swing.junit.testcase.AssertJSwingJUnitTestCase;
import org.junit.Test;

import javax.swing.*;

import static org.assertj.swing.finder.WindowFinder.findDialog;
import static org.assertj.swing.finder.WindowFinder.findFrame;
import static org.assertj.swing.launcher.ApplicationLauncher.application;

public class GUITest extends AssertJSwingJUnitTestCase {

private AWTExceptionHandler awtExceptionHandler;

@Override
protected void onSetUp() {
awtExceptionHandler = new AWTExceptionHandler();
awtExceptionHandler.installExceptionDetectionInEDT();
application(JabRefMain.class).start();
}

@Test
public void testExit() {
FrameFixture mainFrame = findFrame(JabRefFrame.class).using(robot());
exitJabRef(mainFrame);
}

private void exitJabRef(FrameFixture mainFrame) {
mainFrame.menuItemWithPath("File", "Quit").click();
awtExceptionHandler.assertNoExceptions();
}

@Test
public void testNewFile() {
FrameFixture mainFrame = findFrame(JabRefFrame.class).using(robot());
newDatabase(mainFrame);

mainFrame.menuItemWithPath("File", "Close database").click();
exitJabRef(mainFrame);
}

private void newDatabase(FrameFixture mainFrame) {
mainFrame.menuItemWithPath("File", "New BibTeX database").click();
}

@Test
public void testCreateBibtexEntry() {
FrameFixture mainFrame = findFrame(JabRefFrame.class).using(robot());

newDatabase(mainFrame);

mainFrame.menuItemWithPath("BibTeX", "New entry").click();
findDialog(EntryTypeDialog.class).using(robot()).button(new GenericTypeMatcher<JButton>(JButton.class) {

@Override protected boolean isMatching(@Nonnull JButton jButton) {
return "Book".equals(jButton.getText());
}
}).click();

exitJabRef(mainFrame);
}

@Test
public void testOpenAndSavePreferences() {
FrameFixture mainFrame = findFrame(JabRefFrame.class).using(robot());

mainFrame.menuItemWithPath("Options", "Preferences").click();
findDialog(PreferencesDialog.class).using(robot()).button(new GenericTypeMatcher<JButton>(JButton.class) {

@Override protected boolean isMatching(@Nonnull JButton jButton) {
return "OK".equals(jButton.getText());
}
}).click();

exitJabRef(mainFrame);
}

@Test
public void testViewChanges() {
FrameFixture mainFrame = findFrame(JabRefFrame.class).using(robot());

newDatabase(mainFrame);

mainFrame.menuItemWithPath("View", "Increase table font size").click();
mainFrame.menuItemWithPath("View", "Decrease table font size").click();
mainFrame.menuItemWithPath("View", "Web search").click();
mainFrame.menuItemWithPath("View", "Toggle groups interface").click();
mainFrame.menuItemWithPath("View", "Toggle entry preview").click();
mainFrame.menuItemWithPath("View", "Switch preview layout").click();
mainFrame.menuItemWithPath("View", "Hide/show toolbar").click();
mainFrame.menuItemWithPath("View", "Focus entry table").click();

newDatabase(mainFrame);
mainFrame.menuItemWithPath("File", "Close database").click();
exitJabRef(mainFrame);
}

}
4 changes: 3 additions & 1 deletion src/main/java/net/sf/jabref/JabRefMain.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package net.sf.jabref;

import javax.swing.*;

/**
* JabRef MainClass
*/
public class JabRefMain {
public static void main(String[] args) {
new JabRef().start(args);
SwingUtilities.invokeLater(() -> new JabRef().start(args));
}
}
31 changes: 9 additions & 22 deletions src/main/java/net/sf/jabref/gui/JabRefFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -745,29 +745,16 @@ public void about() {
// General preferences dialog. The MacAdapter calls this method when "Preferences..."
// is selected from the application menu.
public void preferences() {
//PrefsDialog.showPrefsDialog(JabRefFrame.this, prefs);
AbstractWorker worker = new AbstractWorker() {

@Override
public void run() {
output(Localization.lang("Opening preferences..."));
if (prefsDialog == null) {
prefsDialog = new PreferencesDialog(JabRefFrame.this, jabRef);
PositionWindow.placeDialog(prefsDialog, JabRefFrame.this);
} else {
prefsDialog.setValues();
}

}
output(Localization.lang("Opening preferences..."));
if (prefsDialog == null) {
prefsDialog = new PreferencesDialog(JabRefFrame.this, jabRef);
PositionWindow.placeDialog(prefsDialog, JabRefFrame.this);
} else {
prefsDialog.setValues();
}

@Override
public void update() {
prefsDialog.setVisible(true);
output("");
}
};
worker.getWorker().run();
worker.getCallBack().update();
prefsDialog.setVisible(true);
output("");
}

public JabRefPreferences prefs() {
Expand Down
63 changes: 25 additions & 38 deletions src/main/java/net/sf/jabref/gui/preftabs/PreferencesDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -248,46 +248,33 @@ public OkAction() {
@Override
public void actionPerformed(ActionEvent e) {

AbstractWorker worker = new AbstractWorker() {

boolean ready = true;


@Override
public void run() {
// First check that all tabs are ready to close:
int count = main.getComponentCount();
Component[] comps = main.getComponents();
for (int i = 0; i < count; i++) {
if (!((PrefsTab) comps[i]).validateSettings()) {
ready = false;
return; // If not, break off.
}
}
// Then store settings and close:
for (int i = 0; i < count; i++) {
((PrefsTab) comps[i]).storeSettings();
}
Globals.prefs.flush();
}

@Override
public void update() {
if (!ready) {
return;
}
setVisible(false);
MainTable.updateRenderers();
GUIGlobals.updateEntryEditorColors();
frame.setupAllTables();
frame.groupSelector.revalidateGroups(); // icons may have
// changed
frame.output(Localization.lang("Preferences recorded."));
boolean ready = true;

// First check that all tabs are ready to close:
int count = main.getComponentCount();
Component[] comps = main.getComponents();
for (int i = 0; i < count; i++) {
if (!((PrefsTab) comps[i]).validateSettings()) {
ready = false;
return; // If not, break off.
}
};
worker.getWorker().run();
worker.getCallBack().update();
}
// Then store settings and close:
for (int i = 0; i < count; i++) {
((PrefsTab) comps[i]).storeSettings();
}
Globals.prefs.flush();

if (!ready) {
return;
}
setVisible(false);
MainTable.updateRenderers();
GUIGlobals.updateEntryEditorColors();
frame.setupAllTables();
frame.groupSelector.revalidateGroups(); // icons may have
// changed
frame.output(Localization.lang("Preferences recorded."));
}
}

Expand Down

0 comments on commit 2cef1fe

Please sign in to comment.