diff --git a/bundles/org.pitest.pitclipse.launch.ui/src/org/pitest/pitclipse/launch/ui/PitLaunchShortcut.java b/bundles/org.pitest.pitclipse.launch.ui/src/org/pitest/pitclipse/launch/ui/PitLaunchShortcut.java index 7d4637a8..89b646d8 100644 --- a/bundles/org.pitest.pitclipse.launch.ui/src/org/pitest/pitclipse/launch/ui/PitLaunchShortcut.java +++ b/bundles/org.pitest.pitclipse.launch.ui/src/org/pitest/pitclipse/launch/ui/PitLaunchShortcut.java @@ -266,17 +266,13 @@ private Optional findExistingLaunchConfiguration(ILaunchCo return Optional.empty(); } else if (candidateCount == 1) { return Optional.ofNullable(candidateConfigs.get(0)); - } else { - // Prompt the user to choose a config. A null result means the user - // cancelled the dialog, in which case this method returns null, - // since cancelling the dialog should also cancel launching - // anything. - ILaunchConfiguration config = chooseConfiguration(candidateConfigs); - if (config != null) { - return Optional.ofNullable(config); - } } - return Optional.empty(); + + // Prompt the user to choose a config. + // if the user does not presses OK we have already interrupted + // the launch with an InterruptedException + ILaunchConfiguration config = chooseConfiguration(candidateConfigs); + return Optional.ofNullable(config); } private List findExistingLaunchConfigurations(ILaunchConfigurationWorkingCopy temporary) throws CoreException { diff --git a/tests/org.pitest.pitclipse.ui.tests/src/org/pitest/pitclipse/ui/behaviours/pageobjects/NoTestsFoundDialog.java b/tests/org.pitest.pitclipse.ui.tests/src/org/pitest/pitclipse/ui/behaviours/pageobjects/NoTestsFoundDialog.java index 3552c220..58b53042 100644 --- a/tests/org.pitest.pitclipse.ui.tests/src/org/pitest/pitclipse/ui/behaviours/pageobjects/NoTestsFoundDialog.java +++ b/tests/org.pitest.pitclipse.ui.tests/src/org/pitest/pitclipse/ui/behaviours/pageobjects/NoTestsFoundDialog.java @@ -34,7 +34,6 @@ public void assertAppears() { bot.label("No tests found"); bot.button("OK").click(); - // Ensure the project is fully created before moving on bot.waitUntil(Conditions.shellCloses(shell)); } diff --git a/tests/org.pitest.pitclipse.ui.tests/src/org/pitest/pitclipse/ui/behaviours/pageobjects/TestConfigurationSelectorDialog.java b/tests/org.pitest.pitclipse.ui.tests/src/org/pitest/pitclipse/ui/behaviours/pageobjects/TestConfigurationSelectorDialog.java new file mode 100644 index 00000000..b8dc0313 --- /dev/null +++ b/tests/org.pitest.pitclipse.ui.tests/src/org/pitest/pitclipse/ui/behaviours/pageobjects/TestConfigurationSelectorDialog.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright 2022 Lorenzo Bettini and contributors + * + * 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 org.pitest.pitclipse.ui.behaviours.pageobjects; + +import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; +import org.eclipse.swtbot.swt.finder.waits.Conditions; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell; + +public class TestConfigurationSelectorDialog { + + private final SWTWorkbenchBot bot; + private SWTBotShell shell; + + public TestConfigurationSelectorDialog(SWTWorkbenchBot bot) { + this.bot = bot; + shell = bot.shell("Select a Test Configuration"); + shell.activate(); + } + + public void cancel() { + bot.button("Cancel").click(); + bot.waitUntil(Conditions.shellCloses(shell)); + } + + public void choose(String option) { + bot.table().select(option); + bot.button("OK").click(); + bot.waitUntil(Conditions.shellCloses(shell)); + } +} diff --git a/tests/org.pitest.pitclipse.ui.tests/src/org/pitest/pitclipse/ui/behaviours/steps/PitclipseSteps.java b/tests/org.pitest.pitclipse.ui.tests/src/org/pitest/pitclipse/ui/behaviours/steps/PitclipseSteps.java index 9e38869c..79bcebc3 100644 --- a/tests/org.pitest.pitclipse.ui.tests/src/org/pitest/pitclipse/ui/behaviours/steps/PitclipseSteps.java +++ b/tests/org.pitest.pitclipse.ui.tests/src/org/pitest/pitclipse/ui/behaviours/steps/PitclipseSteps.java @@ -67,6 +67,19 @@ public void runTest(final String testClassName, final String packageName, final runPitAndWaitForIt(new SelectTestClass(testClassName, packageName, projectName)); } + public void runTest(final String testClassName, final String packageName, final String projectName, + Runnable after) + throws CoreException { + // No need to do a full build: we should be now synchronized with building + // Build the whole workspace to prevent random compilation failures + // ResourcesPlugin.getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, + // new NullProgressMonitor()); + System.out.println(String.format("Run PIT on: %s %s.%s", projectName, packageName, testClassName)); + runPitAndWaitForIt( + new SelectTestClass(testClassName, packageName, projectName), + after); + } + public void runTestMethod(String testMethodName, final String testClassName, final String packageName, final String projectName) throws CoreException { // No need to do a full build: we should be now synchronized with building @@ -171,15 +184,26 @@ public void runtimeOptionsMatch(Map configMap) { * @param runnable which is executed prior to pit */ public void runPitAndWaitForIt(Runnable runnable) { + runPitAndWaitForIt(runnable, () -> {}); + } + + /** + * Runs pit after the given runnable is run and waits for it to finish. + * @param runnable which is executed prior to pit + * @param after which is executed after pit is selected to run (e.g., + * to select an entry in the test selection dialog) + */ + public void runPitAndWaitForIt(Runnable runnable, Runnable after) { assertNoErrorsInWorkspace(); // reset Summary result PitSummary.INSTANCE.resetSummary(); runnable.run(); PAGES.getRunMenu().runPit(); + after.run(); // wait for pit to finish PitSummary.INSTANCE.waitForPitToFinish(); } - + public void assertNoErrorsInWorkspace() { Set errors = errorsInWorkspace(); assertThat(errors, empty()); diff --git a/tests/org.pitest.pitclipse.ui.tests/src/org/pitest/pitclipse/ui/tests/AbstractPitclipseSWTBotTest.java b/tests/org.pitest.pitclipse.ui.tests/src/org/pitest/pitclipse/ui/tests/AbstractPitclipseSWTBotTest.java index 742717c6..ede44e48 100644 --- a/tests/org.pitest.pitclipse.ui.tests/src/org/pitest/pitclipse/ui/tests/AbstractPitclipseSWTBotTest.java +++ b/tests/org.pitest.pitclipse.ui.tests/src/org/pitest/pitclipse/ui/tests/AbstractPitclipseSWTBotTest.java @@ -320,6 +320,11 @@ protected static void runTest(final String testClassName, final String packageNa new PitclipseSteps().runTest(testClassName, packageName, projectName); } + protected static void runTest(final String testClassName, final String packageName, final String projectName, + Runnable after) throws CoreException { + new PitclipseSteps().runTest(testClassName, packageName, projectName, after); + } + protected static void runSingleMethodTest(String testMethodName, final String testClassName, final String packageName, final String projectName) throws CoreException { new PitclipseSteps().runTestMethod(testMethodName, testClassName, packageName, projectName); } diff --git a/tests/org.pitest.pitclipse.ui.tests/src/org/pitest/pitclipse/ui/tests/PitclipseUiRunnerTest.java b/tests/org.pitest.pitclipse.ui.tests/src/org/pitest/pitclipse/ui/tests/PitclipseUiRunnerTest.java index 599a2960..5cc902a9 100644 --- a/tests/org.pitest.pitclipse.ui.tests/src/org/pitest/pitclipse/ui/tests/PitclipseUiRunnerTest.java +++ b/tests/org.pitest.pitclipse.ui.tests/src/org/pitest/pitclipse/ui/tests/PitclipseUiRunnerTest.java @@ -1,5 +1,6 @@ package org.pitest.pitclipse.ui.tests; +import static org.junit.Assert.assertThrows; import static org.pitest.pitclipse.ui.behaviours.pageobjects.PageObjects.PAGES; import java.util.Collections; @@ -10,6 +11,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.pitest.pitclipse.ui.behaviours.pageobjects.NoTestsFoundDialog; +import org.pitest.pitclipse.ui.behaviours.pageobjects.TestConfigurationSelectorDialog; /** * @author Lorenzo Bettini @@ -24,6 +26,7 @@ public class PitclipseUiRunnerTest extends AbstractPitclipseSWTBotTest { private static final String FOO_BAR_PACKAGE = "foo.bar"; private static final String FOO_CLASS = "Foo"; private static final String FOO_TEST_CLASS = "FooTest"; + private static final String FOO_TEST_CLASS_MULTIPLE_LAUNCHES = "FooTestWithSavedConfigurations"; @BeforeClass public static void setupJavaProject() throws CoreException { @@ -195,4 +198,42 @@ public void runBinaryTest() throws CoreException { mutationsAre(Collections.emptyList()); noCoverageReportGenerated(); } + + @Test + public void multipleLaunchConfigurations() throws CoreException { + createMethod(FOO_CLASS, FOO_BAR_PACKAGE, TEST_PROJECT, + "public int doFoo(int i) {\n" + + " return i + 1;\n" + + "}"); + runTest(FOO_TEST_CLASS_MULTIPLE_LAUNCHES, FOO_BAR_PACKAGE, TEST_PROJECT, + () -> + new TestConfigurationSelectorDialog(bot) + .choose(FOO_TEST_CLASS_MULTIPLE_LAUNCHES)); + coverageReportGenerated(1, 0, 0, 2, 0); + runTest(FOO_TEST_CLASS_MULTIPLE_LAUNCHES, FOO_BAR_PACKAGE, TEST_PROJECT, + () -> + new TestConfigurationSelectorDialog(bot) + .choose(FOO_TEST_CLASS_MULTIPLE_LAUNCHES + " (All Mutators)")); + // not just 2 mutants, but much more since in this launch + // we enabled All Mutators + coverageReportGenerated(1, 0, 0, 20, 0); + + @SuppressWarnings("serial") + class MyException extends RuntimeException { + + } + + // cancel the launch + // we also have to interrupt with an exception, otherwise it waits + // for PIT to terminate + assertThrows(MyException.class, () -> + runTest(FOO_TEST_CLASS_MULTIPLE_LAUNCHES, FOO_BAR_PACKAGE, TEST_PROJECT, + () -> + { + new TestConfigurationSelectorDialog(bot) + .cancel(); + throw new MyException(); + }) + ); + } } diff --git a/tests/testprojects/org.pitest.pitclipse.testprojects.emptyclasses/launches/FooTestWithSavedConfigurations (All Mutators).launch b/tests/testprojects/org.pitest.pitclipse.testprojects.emptyclasses/launches/FooTestWithSavedConfigurations (All Mutators).launch new file mode 100644 index 00000000..d391e3b4 --- /dev/null +++ b/tests/testprojects/org.pitest.pitclipse.testprojects.emptyclasses/launches/FooTestWithSavedConfigurations (All Mutators).launch @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/testprojects/org.pitest.pitclipse.testprojects.emptyclasses/launches/FooTestWithSavedConfigurations.launch b/tests/testprojects/org.pitest.pitclipse.testprojects.emptyclasses/launches/FooTestWithSavedConfigurations.launch new file mode 100644 index 00000000..74d0cc71 --- /dev/null +++ b/tests/testprojects/org.pitest.pitclipse.testprojects.emptyclasses/launches/FooTestWithSavedConfigurations.launch @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/testprojects/org.pitest.pitclipse.testprojects.emptyclasses/src/foo/bar/FooTestWithSavedConfigurations.java b/tests/testprojects/org.pitest.pitclipse.testprojects.emptyclasses/src/foo/bar/FooTestWithSavedConfigurations.java new file mode 100644 index 00000000..78f72d36 --- /dev/null +++ b/tests/testprojects/org.pitest.pitclipse.testprojects.emptyclasses/src/foo/bar/FooTestWithSavedConfigurations.java @@ -0,0 +1,5 @@ +package foo.bar; + +public class FooTestWithSavedConfigurations { + +}