From bddeb9f5a921258bf37bee4fe5d102a7e3006475 Mon Sep 17 00:00:00 2001 From: jeb228 Date: Mon, 16 Aug 2010 18:15:31 +0000 Subject: [PATCH] NIHVIVO-222 Allow the user to ignore entire suites using the ignored_tests file. --- .../utilities/testrunner/IgnoredTests.java | 78 ++++++- .../vitro/utilities/testrunner/Listener.java | 12 +- .../utilities/testrunner/ModelCleaner.java | 2 +- .../utilities/testrunner/SeleniumRunner.java | 25 ++- .../testrunner/IgnoredTestsTest.java | 191 ++++++++++++++++++ 5 files changed, 301 insertions(+), 7 deletions(-) create mode 100644 utilities/testrunner/test/edu/cornell/mannlib/vitro/utilities/testrunner/IgnoredTestsTest.java diff --git a/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/IgnoredTests.java b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/IgnoredTests.java index 8140cd200..afb9d2cc8 100644 --- a/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/IgnoredTests.java +++ b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/IgnoredTests.java @@ -32,6 +32,10 @@ public class IgnoredTests { * name, a comma (with optional space), the test name (with optional space) * and optionally a comment, starting with a '#'. *

+ * If the test name is an asterisk '*', then the entire suite will be + * ignored. + *

+ *

*/ public IgnoredTests(File file) { this.file = file; @@ -76,6 +80,13 @@ public class IgnoredTests { this.tests = Collections.unmodifiableList(tests); } + /** + * Package access -- only used in unit tests. + */ + List getList() { + return new ArrayList(tests); + } + /** * Is this test ignored or not? */ @@ -88,6 +99,18 @@ public class IgnoredTests { return false; } + /** + * Is this entire suite ignored? + */ + public boolean isIgnored(String suiteName) { + for (IgnoredTestInfo test : tests) { + if (test.matchesEntireSuite(suiteName)) { + return true; + } + } + return false; + } + /** * If this test is ignored, what is the reason? If not, return an empty * string. @@ -101,6 +124,19 @@ public class IgnoredTests { return ""; } + /** + * If this suite is ignored, what is the reason? If not, return an empty + * string. + */ + public String getReasonForIgnoring(String suiteName) { + for (IgnoredTestInfo test : tests) { + if (test.matchesEntireSuite(suiteName)) { + return test.comment; + } + } + return ""; + } + public String toString() { String s = " ignored tests from " + file.getPath() + "\n"; for (IgnoredTestInfo test : tests) { @@ -109,7 +145,10 @@ public class IgnoredTests { return s; } - private static class IgnoredTestInfo { + /** + * Package access so it can be used in unit tests. + */ + static class IgnoredTestInfo { final String suiteName; final String testName; final String comment; @@ -122,7 +161,42 @@ public class IgnoredTests { public boolean matches(String suiteName, String testName) { return this.suiteName.equals(suiteName) - && this.testName.equals(testName); + && (this.testName.equals(testName) || this.testName + .equals("*")); + } + + public boolean matchesEntireSuite(String suiteName) { + return this.suiteName.equals(suiteName) + && this.testName.equals("*"); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj == null) { + return false; + } + if (!obj.getClass().equals(this.getClass())) { + return false; + } + IgnoredTestInfo that = (IgnoredTestInfo) obj; + return this.suiteName.equals(that.suiteName) + && this.testName.equals(that.testName) + && this.comment.equals(that.comment); + } + + @Override + public int hashCode() { + return suiteName.hashCode() ^ testName.hashCode() + ^ comment.hashCode(); + } + + @Override + public String toString() { + return "IgnoredTestInfo['" + suiteName + "', '" + testName + "', '" + + comment + "']"; } } diff --git a/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/Listener.java b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/Listener.java index d1c8ce92e..904965a78 100644 --- a/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/Listener.java +++ b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/Listener.java @@ -25,7 +25,7 @@ public class Listener { private final Writer writer; // ---------------------------------------------------------------------- - // Listener methods + // Constructors // ---------------------------------------------------------------------- public Listener(PrintStream out) { @@ -40,6 +40,14 @@ public class Listener { // Listener methods // ---------------------------------------------------------------------- + public void suiteIgnored(File suite) { + log("Suite '" + suite.getName() + "' ignored."); + } + + public void suiteAdded(File suite) { + log("Suite '" + suite.getName() + "' added."); + } + public void runStarted() { log("Run started."); } @@ -56,7 +64,7 @@ public class Listener { public void runStopped() { log("Run stopped."); } - + public void cleanOutputStart(File outputDirectory) { log("Output area cleaning started: " + outputDirectory.getPath()); } diff --git a/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/ModelCleaner.java b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/ModelCleaner.java index e10d3b7d1..ed8ac4c3e 100644 --- a/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/ModelCleaner.java +++ b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/ModelCleaner.java @@ -51,7 +51,7 @@ public class ModelCleaner { /** * Stop Tomcat and wait the prescribed number of seconds for it to clean up. */ - private void stopTheWebapp() throws CommandRunnerException { + public void stopTheWebapp() throws CommandRunnerException { String tomcatStopCommand = properties.getTomcatStopCommand(); int tomcatStopDelay = properties.getTomcatStopDelay(); diff --git a/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/SeleniumRunner.java b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/SeleniumRunner.java index 8b332a837..c252121a2 100644 --- a/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/SeleniumRunner.java +++ b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/SeleniumRunner.java @@ -52,6 +52,17 @@ public class SeleniumRunner { } listener.suiteStopped(suiteDir); } + + // If we've been starting and stopping Tomcat, + // stop it one more time. + if (parms.isCleanModel()) { + try { + modelCleaner.stopTheWebapp(); + } catch (CommandRunnerException e) { + throw new FatalException(e); + } + } + listener.runEndTime(); Status status = outputManager.summarizeOutput(); success = (status == Status.OK); @@ -69,9 +80,19 @@ public class SeleniumRunner { } private static void selectAllSuites(SeleniumRunnerParameters parms) { + Listener listener = parms.getListener(); + IgnoredTests ignored = parms.getIgnoredTests(); List suites = new ArrayList(); for (File parentDir : parms.getSuiteParentDirectories()) { - suites.addAll(parms.findSuiteDirs(parentDir)); + for (File suite : parms.findSuiteDirs(parentDir)) { + String suiteName = suite.getName(); + if (ignored.isIgnored(suiteName)) { + listener.suiteIgnored(suite); + } else { + listener.suiteAdded(suite); + suites.add(suite); + } + } } parms.setSelectedSuites(suites); } @@ -126,7 +147,7 @@ public class SeleniumRunner { SeleniumRunner runner = new SeleniumRunner(parms); success = runner.runSelectedSuites(); } - + System.out.println("Exiting SeleniumRunner"); System.exit(success ? 0 : -1); } diff --git a/utilities/testrunner/test/edu/cornell/mannlib/vitro/utilities/testrunner/IgnoredTestsTest.java b/utilities/testrunner/test/edu/cornell/mannlib/vitro/utilities/testrunner/IgnoredTestsTest.java new file mode 100644 index 000000000..a5554cbbf --- /dev/null +++ b/utilities/testrunner/test/edu/cornell/mannlib/vitro/utilities/testrunner/IgnoredTestsTest.java @@ -0,0 +1,191 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.utilities.testrunner; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.HashSet; +import java.util.Set; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import edu.cornell.mannlib.vitro.utilities.testrunner.IgnoredTests.IgnoredTestInfo; + +/** + * Check that the ignored_tests.txt file is being parsed correctly. + */ +public class IgnoredTestsTest { + private static final String TEST_WITH_REASON = "test with reason"; + private static final String TEST_NO_REASON = "test with no reason"; + private static final String TEST_NOT_IGNORED = "test not ignored"; + private static final String TEST_FROM_IGNORED_SUITE = "test from ignored suite"; + private static final String SUITE_WITH_TESTS = "suite with tests"; + private static final String SUITE_WITH_REASON = "entire suite with reason"; + private static final String SUITE_NO_REASON = "entire suite with no reason"; + private static final String SUITE_NOT_IGNORED = "entire suite not ignored"; + private static final String REASON_FOR_TEST = "the reason for the test"; + private static final String REASON_FOR_SUITE = "the reason for the suite"; + private static final String NO_REASON = ""; + + private static final String FILE_CONTENTS = "# This line is a comment \n" + + "! This line is also, and so is the blank one\n" + + "\n" + + (SUITE_WITH_TESTS + ", " + TEST_NO_REASON + "\n") + + (SUITE_WITH_TESTS + ", " + TEST_WITH_REASON + " # " + + REASON_FOR_TEST + "\n") + (SUITE_NO_REASON + ", *\n") + + (SUITE_WITH_REASON + ", * # " + REASON_FOR_SUITE + "\n"); + + private static final String BAD_CONTENTS = "suite but no test # doesn't match."; + + /* + * Ignore any blank line, or any line starting with '#' or '!'

Each + * other line describes an ignored test. The line contains the suite name, a + * comma (with optional space), the test name (with optional space) and + * optionally a comment, starting with a '#'.

If the test name is an + * asterisk '*', then the entire suite will be ignored.

+ */ + + private static File ignoreFile; + private static File badFile; + + @BeforeClass + public static void initializeTheFile() throws IOException { + ignoreFile = File.createTempFile("IgnoredTestsTest", ""); + + Writer writer = new FileWriter(ignoreFile); + try { + writer.write(FILE_CONTENTS); + } finally { + writer.close(); + } + } + + @BeforeClass + public static void initializeBadFile() throws IOException { + badFile = File.createTempFile("IgnoredTestsTest", ""); + + Writer writer = new FileWriter(badFile); + try { + writer.write(BAD_CONTENTS); + } finally { + writer.close(); + } + } + + @AfterClass + public static void cleanup() throws IOException { + ignoreFile.delete(); + badFile.delete(); + } + + private IgnoredTests ignored; + + @Before + public void readTheFile() { + ignored = new IgnoredTests(ignoreFile); + } + + @Test(expected = FatalException.class) + public void readBadFile() { + new IgnoredTests(badFile); + } + + @Test + public void getList() { + Set expected = new HashSet(); + expected.add(new IgnoredTestInfo(SUITE_WITH_TESTS, TEST_NO_REASON, + NO_REASON)); + expected.add(new IgnoredTestInfo(SUITE_WITH_TESTS, TEST_WITH_REASON, + REASON_FOR_TEST)); + expected.add(new IgnoredTestInfo(SUITE_NO_REASON, "*", NO_REASON)); + expected.add(new IgnoredTestInfo(SUITE_WITH_REASON, "*", + REASON_FOR_SUITE)); + Set actual = new HashSet( + ignored.getList()); + assertEquals("list of tests", expected, actual); + } + + @Test + public void isIgnoredTestYes() { + assertTrue("ignored test", + ignored.isIgnored(SUITE_WITH_TESTS, TEST_NO_REASON)); + } + + @Test + public void isIgnoredTestNo() { + assertFalse("not ignored test", + ignored.isIgnored(SUITE_WITH_TESTS, TEST_NOT_IGNORED)); + } + + @Test + public void isIgnoredTestFromSuite() { + assertTrue("test from ignored suite", + ignored.isIgnored(SUITE_WITH_REASON, TEST_FROM_IGNORED_SUITE)); + } + + @Test + public void getReasonTestYes() { + assertEquals( + "test with reason", + REASON_FOR_TEST, + ignored.getReasonForIgnoring(SUITE_WITH_TESTS, TEST_WITH_REASON)); + } + + @Test + public void getReasonTestNo() { + assertEquals( + "test not ignored", + NO_REASON, + ignored.getReasonForIgnoring(SUITE_WITH_TESTS, TEST_NOT_IGNORED)); + } + + @Test + public void getReasonTestNoReason() { + assertEquals("test with no reason", NO_REASON, + ignored.getReasonForIgnoring(SUITE_WITH_TESTS, TEST_NO_REASON)); + } + + @Test + public void getReasonTestFromSuite() { + assertEquals("test from ignored suite", REASON_FOR_SUITE, + ignored.getReasonForIgnoring(SUITE_WITH_REASON, + TEST_FROM_IGNORED_SUITE)); + } + + @Test + public void isIgnoredSuiteYes() { + assertTrue("ignored suite", ignored.isIgnored(SUITE_WITH_REASON)); + } + + @Test + public void isIgnoredSuiteNo() { + assertFalse("not ignored suite", ignored.isIgnored(SUITE_NOT_IGNORED)); + } + + @Test + public void getReasonSuiteYes() { + assertEquals("suite with reason", REASON_FOR_SUITE, + ignored.getReasonForIgnoring(SUITE_WITH_REASON)); + } + + @Test + public void getReasonSuiteNo() { + assertEquals("suite not ignored", NO_REASON, + ignored.getReasonForIgnoring(SUITE_NOT_IGNORED)); + } + + @Test + public void getReasonSuiteNoReason() { + assertEquals("suite with no reason", NO_REASON, + ignored.getReasonForIgnoring(SUITE_NO_REASON)); + } +}