mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-19738: test added
Run tests, then delete files, and try to rerun it. Message and exc. should be displayed
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
__author__ = 'Ilya.Kazakevich'
|
||||
import unittest
|
||||
import time
|
||||
|
||||
class TestMe2(unittest.TestCase):
|
||||
def test_pass(self):
|
||||
time.sleep(1)
|
||||
|
||||
def test_raise(self):
|
||||
raise ValueError
|
||||
|
||||
class TestMe(unittest.TestCase):
|
||||
def test_pass2(self):
|
||||
pass
|
||||
@@ -52,7 +52,7 @@ import java.util.List;
|
||||
* you need to implement {@link #getEnvironmentToRerun(RunContentDescriptor)}, accept last run descriptor and return
|
||||
* {@link ExecutionEnvironment} to rerun (probably obtained from descriptor).
|
||||
* <p/>
|
||||
* It also has {@link #getAvailableRunnersForLastRun()} with list of strings that represents runner ids available for last run.
|
||||
* It also has {@link #getAvailableRunnersForLastRun()} with list of runners that represents runner ids available for last run.
|
||||
*
|
||||
* @param <CONF_T> configuration class this runner supports
|
||||
* @author Ilya.Kazakevich
|
||||
@@ -65,7 +65,7 @@ public abstract class ConfigurationBasedProcessRunner<CONF_T extends AbstractPyt
|
||||
private final Class<CONF_T> myExpectedConfigurationType;
|
||||
|
||||
@NotNull
|
||||
private final List<String> myAvailableRunnersForLastRun = new ArrayList<String>();
|
||||
private final List<ProgramRunner<?>> myAvailableRunnersForLastRun = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Environment to be used to run instead of factory. Used to rerun
|
||||
@@ -75,7 +75,7 @@ public abstract class ConfigurationBasedProcessRunner<CONF_T extends AbstractPyt
|
||||
/**
|
||||
* Process descriptor of last run
|
||||
*/
|
||||
private RunContentDescriptor myLastProcessDescriptor;
|
||||
protected RunContentDescriptor myLastProcessDescriptor;
|
||||
|
||||
/**
|
||||
* @param configurationFactory factory tp create configurations
|
||||
@@ -114,7 +114,7 @@ public abstract class ConfigurationBasedProcessRunner<CONF_T extends AbstractPyt
|
||||
for (final ProgramRunner<?> runner : ProgramRunner.PROGRAM_RUNNER_EP.getExtensions()) {
|
||||
for (final Executor executor : Executor.EXECUTOR_EXTENSION_NAME.getExtensions()) {
|
||||
if (runner.canRun(executor.getId(), executionEnvironment.getRunProfile())) {
|
||||
myAvailableRunnersForLastRun.add(runner.getRunnerId());
|
||||
myAvailableRunnersForLastRun.add(runner);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -222,7 +222,7 @@ public abstract class ConfigurationBasedProcessRunner<CONF_T extends AbstractPyt
|
||||
* Use it to check if desired runner (like debugger) exists
|
||||
*/
|
||||
@NotNull
|
||||
public final List<String> getAvailableRunnersForLastRun() {
|
||||
public final List<ProgramRunner<?>> getAvailableRunnersForLastRun() {
|
||||
return Collections.unmodifiableList(myAvailableRunnersForLastRun);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package com.jetbrains.env;
|
||||
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.configurations.ConfigurationFactory;
|
||||
import com.intellij.execution.impl.ConsoleViewImpl;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.execution.runners.ProgramRunner;
|
||||
import com.intellij.execution.testframework.AbstractTestProxy;
|
||||
import com.intellij.execution.testframework.Filter;
|
||||
import com.intellij.execution.testframework.actions.RerunFailedActionsTestTools;
|
||||
@@ -12,12 +15,14 @@ import com.intellij.execution.ui.RunContentDescriptor;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.jetbrains.python.run.AbstractPythonRunConfigurationParams;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.junit.Assert;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Runner for tests. Provides access to test console and test results.
|
||||
@@ -170,4 +175,32 @@ public class PyAbstractTestProcessRunner<CONF_T extends AbstractPythonRunConfigu
|
||||
public int getCurrentRerunStep() {
|
||||
return myCurrentRerunStep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rerun current tests. Make sure there is at least one failed test.
|
||||
* <strong>Run in AWT thread only!</strong>
|
||||
*/
|
||||
public void rerunFailedTests() {
|
||||
assert getFailedTestsCount() > 0 : "No failed tests. What you want to rerun?";
|
||||
assert myLastProcessDescriptor != null : "No last run descriptor. First run tests at least one time";
|
||||
final List<ProgramRunner<?>> run = getAvailableRunnersForLastRun();
|
||||
Assert.assertFalse("No runners to rerun", run.isEmpty());
|
||||
final ProgramRunner<?> runner = run.get(0);
|
||||
|
||||
final ExecutionEnvironment restartAction = RerunFailedActionsTestTools.findRestartAction(myLastProcessDescriptor);
|
||||
Assert.assertNotNull("No restart action", restartAction);
|
||||
|
||||
final Ref<ProcessHandler> handlerRef = new Ref<>();
|
||||
try {
|
||||
runner.execute(restartAction, descriptor -> handlerRef.set(descriptor.getProcessHandler()));
|
||||
}
|
||||
catch (final ExecutionException e) {
|
||||
throw new AssertionError("ExecutionException can't be thrown in tests. Probably, API changed. Got: " + e);
|
||||
}
|
||||
final ProcessHandler handler = handlerRef.get();
|
||||
if (handler == null) {
|
||||
return;
|
||||
}
|
||||
handler.waitFor();
|
||||
}
|
||||
}
|
||||
|
||||
+77
-5
@@ -5,9 +5,13 @@ import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.ui.TestDialog;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.testFramework.LoggedErrorProcessor;
|
||||
import com.intellij.testFramework.UsefulTestCase;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.SystemProperties;
|
||||
@@ -25,9 +29,7 @@ import org.junit.runner.Description;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author traff
|
||||
@@ -48,6 +50,12 @@ public abstract class PyEnvTestCase {
|
||||
|
||||
private static final boolean STAGING_ENV = SystemProperties.getBooleanProperty("pycharm.staging_env", false);
|
||||
|
||||
|
||||
/**
|
||||
* Logger to be used with {@link #startMessagesCapture()}
|
||||
*/
|
||||
private PyTestMessagesLogger myLogger;
|
||||
|
||||
/**
|
||||
* Tags that should exist between all tags, available on all interpreters for test to run.
|
||||
* See {@link #PyEnvTestCase(String...)}
|
||||
@@ -150,8 +158,6 @@ public abstract class PyEnvTestCase {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
protected boolean runInDispatchThread() {
|
||||
return false;
|
||||
}
|
||||
@@ -285,5 +291,71 @@ public abstract class PyEnvTestCase {
|
||||
public static String joinStrings(Collection<String> roots, String rootsName) {
|
||||
return roots.size() > 0 ? rootsName + StringUtil.join(roots, ", ") + "\n" : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture all messages and error logs and store them to be obtained with {@link #getCapturesMessages()}
|
||||
* and stopped with {@link #stopMessageCapture()}
|
||||
*/
|
||||
protected final void startMessagesCapture() {
|
||||
myLogger = new PyTestMessagesLogger();
|
||||
LoggedErrorProcessor.setNewInstance(myLogger);
|
||||
Messages.setTestDialog(myLogger);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return captures messages (first start with {@link #startMessagesCapture()}).
|
||||
* Logged exceptions -- list of messages to be displayed (never null)
|
||||
*/
|
||||
@NotNull
|
||||
protected final Pair<List<Throwable>, List<String>> getCapturesMessages() {
|
||||
assert myLogger != null : "Capturing not enabled";
|
||||
return Pair.create(Collections.unmodifiableList(myLogger.myExceptions), Collections.unmodifiableList(myLogger.myMessages));
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop message capturing started with {@link #startMessagesCapture()}
|
||||
*/
|
||||
protected final void stopMessageCapture() {
|
||||
LoggedErrorProcessor.restoreDefaultProcessor();
|
||||
Messages.setTestDialog(TestDialog.DEFAULT);
|
||||
myLogger = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always call parrent when overwrite
|
||||
*/
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
// We can stop message capturing even if it was not started as cleanup process.
|
||||
stopMessageCapture();
|
||||
}
|
||||
|
||||
/**
|
||||
* Logger to be used with {@link #startMessagesCapture()}
|
||||
*/
|
||||
private static final class PyTestMessagesLogger extends LoggedErrorProcessor implements TestDialog {
|
||||
|
||||
private final List<String> myMessages = new ArrayList<>();
|
||||
private final List<Throwable> myExceptions = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public int show(final String message) {
|
||||
myMessages.add(message);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processWarn(final String message, final Throwable t, @NotNull final org.apache.log4j.Logger logger) {
|
||||
myExceptions.add(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processError(final String message,
|
||||
final Throwable t,
|
||||
final String[] details,
|
||||
@NotNull final org.apache.log4j.Logger logger) {
|
||||
myExceptions.add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+64
-1
@@ -1,9 +1,15 @@
|
||||
package com.jetbrains.env.python.testing;
|
||||
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.EdtTestUtil;
|
||||
import com.intellij.testFramework.fixtures.CodeInsightTestFixture;
|
||||
import com.jetbrains.env.PyEnvTestCase;
|
||||
import com.jetbrains.env.Staging;
|
||||
import com.jetbrains.env.ut.PyUnitTestProcessRunner;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.psi.LanguageLevel;
|
||||
import com.jetbrains.python.testing.PythonTestConfigurationsModel;
|
||||
import com.jetbrains.python.testing.unittest.PythonUnitTestConfigurationProducer;
|
||||
@@ -12,8 +18,10 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
@@ -67,6 +75,62 @@ public final class PythonUnitTestingTest extends PyEnvTestCase {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run tests, delete file and click "rerun" should throw exception and display error since test ids do not point to correct PSI
|
||||
* from that moment
|
||||
*/
|
||||
@Test
|
||||
public void testCantRerun() throws Exception {
|
||||
startMessagesCapture();
|
||||
|
||||
runPythonTest(new PyUnitTestProcessWithConsoleTestTask("/testRunner/env/unit", "test_with_skips_and_errors.py") {
|
||||
|
||||
@Override
|
||||
protected void checkTestResults(@NotNull final PyUnitTestProcessRunner runner,
|
||||
@NotNull final String stdout,
|
||||
@NotNull final String stderr,
|
||||
@NotNull final String all) {
|
||||
assert runner.getFailedTestsCount() > 0 : "We need failed tests to test broken rerun";
|
||||
|
||||
startMessagesCapture();
|
||||
|
||||
EdtTestUtil.runInEdtAndWait((Runnable)() -> {
|
||||
deleteAllTestFiles(myFixture);
|
||||
runner.rerunFailedTests();
|
||||
});
|
||||
|
||||
final List<Throwable> throwables = getCapturesMessages().first;
|
||||
Assert.assertThat("Exception shall be thrown", throwables, not(emptyCollectionOf(Throwable.class)));
|
||||
final Throwable exception = throwables.get(0);
|
||||
Assert.assertThat("ExecutionException should be thrown", exception, instanceOf(ExecutionException.class));
|
||||
Assert.assertThat("Wrong text", exception.getMessage(), equalTo(PyBundle.message("runcfg.tests.cant_rerun")));
|
||||
Assert.assertThat("No messages displayed for exception", getCapturesMessages().second, not(emptyCollectionOf(String.class)));
|
||||
|
||||
|
||||
stopMessageCapture();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all files in temp. folder
|
||||
*/
|
||||
private static void deleteAllTestFiles(@NotNull final CodeInsightTestFixture fixture) {
|
||||
ApplicationManager.getApplication().runWriteAction(() -> {
|
||||
final VirtualFile testRoot = fixture.getTempDirFixture().getFile(".");
|
||||
assert testRoot != null : "No temp path?";
|
||||
try {
|
||||
for (final VirtualFile child : testRoot.getChildren()) {
|
||||
child.delete(null);
|
||||
}
|
||||
}
|
||||
catch (final IOException e) {
|
||||
throw new AssertionError(String.format("Failed to delete files in %s : %s", testRoot, e));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that skipped and erroneous tests do not lead to suite ignorance
|
||||
*/
|
||||
@@ -227,5 +291,4 @@ public final class PythonUnitTestingTest extends PyEnvTestCase {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user