diff --git a/python/helpers/pycharm/_jb_tox_runner.py b/python/helpers/pycharm/_jb_tox_runner.py index 2b82041edb79..57abbc16596e 100644 --- a/python/helpers/pycharm/_jb_tox_runner.py +++ b/python/helpers/pycharm/_jb_tox_runner.py @@ -81,27 +81,26 @@ class _MySession(tox_session.Session): class _Unit2(object): - def fix(self, command, dir_to_run, bin): + def fix(self, command, bin): if command[0] == "unit2": - return [bin, os.path.join(helpers_dir, "utrunner.py"), dir_to_run] + command[1:] + ["true"] + return [bin, os.path.join(helpers_dir, "utrunner.py")] + command[1:] + ["true"] elif command == ["python", "-m", "unittest", "discover"]: - return [bin, os.path.join(helpers_dir, "utrunner.py"), dir_to_run, "true"] + return [bin, os.path.join(helpers_dir, "utrunner.py"), "true"] return None class _PyTest(object): - def fix(self, command, dir_to_run, bin): + def fix(self, command, bin): if command[0] != "py.test": return None - normal_path = os.path.normpath(dir_to_run) + os.sep - return [bin, os.path.join(helpers_dir, "pytestrunner.py"), "-p", "pytest_teamcity", normal_path] + command[1:] + return [bin, os.path.join(helpers_dir, "pytestrunner.py"), "-p", "pytest_teamcity"] + command[1:] class _Nose(object): - def fix(self, command, dir_to_run, bin): + def fix(self, command, bin): if command[0] != "nosetests": return None - return [bin, os.path.join(helpers_dir, "noserunner.py"), dir_to_run] + command[1:] + return [bin, os.path.join(helpers_dir, "noserunner.py")] + command[1:] _RUNNERS = [_Unit2(), _PyTest(), _Nose()] @@ -116,10 +115,9 @@ for env, tmp_config in config.envconfigs.items(): continue for fixer in _RUNNERS: _env = config.envconfigs[env] - dir_to_run = str(_env.changedir) for i, command in enumerate(commands): if command: - fixed_command = fixer.fix(command, dir_to_run, str(_env.envpython)) + fixed_command = fixer.fix(command, str(_env.envpython)) if fixed_command: commands[i] = fixed_command tmp_config.commands = commands diff --git a/python/helpers/pycharm/utrunner.py b/python/helpers/pycharm/utrunner.py index 180dada8d602..f387e2c824d4 100644 --- a/python/helpers/pycharm/utrunner.py +++ b/python/helpers/pycharm/utrunner.py @@ -122,6 +122,9 @@ if __name__ == "__main__": all = unittest.TestSuite() pure_unittest = True + if len(sys.argv) == 2: # If folder not provided, we need pretend folder is current + sys.argv.insert(1, ".") + options = {} for arg in sys.argv[1:-1]: arg = arg.strip() diff --git a/python/testData/toxtest/toxDoubleRun/setup.py b/python/testData/toxtest/toxDoubleRun/setup.py new file mode 100644 index 000000000000..9b877e657e2a --- /dev/null +++ b/python/testData/toxtest/toxDoubleRun/setup.py @@ -0,0 +1,14 @@ +#!/usr/bin/python + +import os + +from setuptools import setup +from setuptools import find_packages + +package = 'python_package_template' +setup_dir = os.path.dirname(os.path.abspath(__file__)) + +setup(name=package, + version="!", + include_package_data=True, + ) diff --git a/python/testData/toxtest/toxDoubleRun/test/unit/__init__.py b/python/testData/toxtest/toxDoubleRun/test/unit/__init__.py new file mode 100644 index 000000000000..3ccf298fdf6c --- /dev/null +++ b/python/testData/toxtest/toxDoubleRun/test/unit/__init__.py @@ -0,0 +1 @@ +__author__ = 'rpocase' diff --git a/python/testData/toxtest/toxDoubleRun/test/unit/test_single_test.py b/python/testData/toxtest/toxDoubleRun/test/unit/test_single_test.py new file mode 100644 index 000000000000..97c7c48803d0 --- /dev/null +++ b/python/testData/toxtest/toxDoubleRun/test/unit/test_single_test.py @@ -0,0 +1,5 @@ +from time import sleep + + +def test_empty_class(): + sleep(1) diff --git a/python/testData/toxtest/toxDoubleRun/tox.ini b/python/testData/toxtest/toxDoubleRun/tox.ini new file mode 100644 index 000000000000..f3f4cf26f680 --- /dev/null +++ b/python/testData/toxtest/toxDoubleRun/tox.ini @@ -0,0 +1,10 @@ +[tox] +envlist = py27 + + +[testenv] +commands =py.test test/unit + + +deps = pytest + diff --git a/python/testSrc/com/jetbrains/env/PyToxTest.java b/python/testSrc/com/jetbrains/env/PyToxTest.java index cf8eb44b615e..ab4fec20c309 100644 --- a/python/testSrc/com/jetbrains/env/PyToxTest.java +++ b/python/testSrc/com/jetbrains/env/PyToxTest.java @@ -29,7 +29,6 @@ import org.jetbrains.annotations.Nullable; import org.junit.Assert; import org.junit.Test; -import java.io.IOException; import java.util.*; /** @@ -46,7 +45,7 @@ public final class PyToxTest extends PyEnvTestCase { * Simply ensure tox runner works */ @Test - public void testToxSimpleRun() throws IOException { + public void testToxSimpleRun() { runPythonTest(new MyPyProcessWithConsoleTestTask("/toxtest/toxSimpleRun/", 2, new MyTestProcessRunner(), Arrays.asList( @@ -54,15 +53,15 @@ public final class PyToxTest extends PyEnvTestCase { Pair.create("py26", new InterpreterExpectations( "AttributeError: 'module' object has no attribute 'skip'", false)), Pair.create("py27", new InterpreterExpectations("", true)) - ) - )); + ), + Integer.MAX_VALUE)); } /** * Check tox nose runner */ @Test - public void testToxNose() throws IOException { + public void testToxNose() { runPythonTest(new MyPyProcessWithConsoleTestTask("/toxtest/toxNose/", 1, new MyTestProcessRunner(), Arrays.asList( @@ -71,8 +70,8 @@ public final class PyToxTest extends PyEnvTestCase { // Does not support 3.4 Pair.create("py32", new InterpreterExpectations("SyntaxError", false)), Pair.create("py34", new InterpreterExpectations("SyntaxError", false)) - ) - ) + ), + Integer.MAX_VALUE) ); } @@ -80,7 +79,7 @@ public final class PyToxTest extends PyEnvTestCase { * Check tox pytest runner */ @Test - public void testToxPyTest() throws IOException { + public void testToxPyTest() { runPythonTest(new MyPyProcessWithConsoleTestTask("/toxtest/toxPyTest/", 1, new MyTestProcessRunner(), Arrays.asList( @@ -89,8 +88,8 @@ public final class PyToxTest extends PyEnvTestCase { // Does not support 3.4 Pair.create("py32", new InterpreterExpectations("SyntaxError", false)), Pair.create("py34", new InterpreterExpectations("SyntaxError", false)) - ) - ) + ), + Integer.MAX_VALUE) ); } @@ -98,7 +97,7 @@ public final class PyToxTest extends PyEnvTestCase { * Check tox unit runner */ @Test - public void testToxUnitTest() throws IOException { + public void testToxUnitTest() { runPythonTest(new MyPyProcessWithConsoleTestTask("/toxtest/toxUnitTest/", 1, new MyTestProcessRunner(), Arrays.asList( @@ -107,8 +106,8 @@ public final class PyToxTest extends PyEnvTestCase { // Does not support 3.4 Pair.create("py32", new InterpreterExpectations("SyntaxError", false)), Pair.create("py34", new InterpreterExpectations("SyntaxError", false)) - ) - ) + ), + Integer.MAX_VALUE) ); } @@ -124,18 +123,31 @@ public final class PyToxTest extends PyEnvTestCase { Pair.create("py27", new InterpreterExpectations("ython 2.7", true)), Pair.create("py32", new InterpreterExpectations("", true)), Pair.create("py34", new InterpreterExpectations("", true)) - ) - ) + ), + Integer.MAX_VALUE) ); + } + /** + * Ensures test is not launched 2 times because folder added 2 times + */ + @Test + public void testDoubleRun() throws Exception { + runPythonTest(new MyPyProcessWithConsoleTestTask("/toxtest/toxDoubleRun/", 1, + new MyTestProcessRunner(), + Collections.singletonList( + Pair.create("py27", new InterpreterExpectations("", true)) + ), + 1) + ); } /** * Big test which should run on any interpreter and check its output */ @Test - public void testToxSuccessTest() throws IOException { + public void testToxSuccessTest() { runPythonTest(new MyPyProcessWithConsoleTestTask("/toxtest/toxSuccess/", 1, new MyTestProcessRunner(), Arrays.asList( @@ -144,8 +156,8 @@ public final class PyToxTest extends PyEnvTestCase { // Should have output Pair.create("py32", new InterpreterExpectations("I am 3.2", true)), Pair.create("py34", new InterpreterExpectations("I am 3.4", true)) - ) - ) + ), + Integer.MAX_VALUE) ); } @@ -154,20 +166,23 @@ public final class PyToxTest extends PyEnvTestCase { @NotNull private final Map myInterpreters = new HashMap<>(); private final int myMinimumSuccessTestCount; + private final int myMaximumSuccessTestCount; @NotNull private final MyTestProcessRunner myRunner; /** - * @param relativeTestDataPath TODO: DOC * @param minimumSuccessTestCount how many success tests should be * @param interpreterExpectations interpreter_name -] expected result + * @param maximumTestCount max number of success tests */ private MyPyProcessWithConsoleTestTask(@Nullable final String relativeTestDataPath, final int minimumSuccessTestCount, @NotNull final MyTestProcessRunner runner, - @NotNull final Collection> interpreterExpectations) { + @NotNull final Iterable> interpreterExpectations, + final int maximumTestCount) { super(relativeTestDataPath, SdkCreationType.EMPTY_SDK); myMinimumSuccessTestCount = minimumSuccessTestCount; + myMaximumSuccessTestCount = maximumTestCount; myRunner = runner; for (final Pair interpreterExpectation : interpreterExpectations) { myInterpreters.put(interpreterExpectation.first, interpreterExpectation.second); @@ -218,15 +233,20 @@ public final class PyToxTest extends PyEnvTestCase { if (interpreterSuite.getChildren().size() == 1 && interpreterSuite.getChildren().get(0).getName().endsWith("SKIP")) { // The only reason it may be skipped is it does not exist and skip_missing_interpreters = True final String output = getTestOutput(interpreterSuite); - Assert.assertThat("Test marked skipped but not because interpreter not found", output, Matchers.containsString("InterpreterNotFound")); + Assert.assertThat("Test marked skipped but not because interpreter not found", output, + Matchers.containsString("InterpreterNotFound")); } // Interpretr run success, //At least one interpreter tests should passed - Assert.assertThat(String.format("No test passed, should %s at least", myMinimumSuccessTestCount), - new SMRootTestsCounter(interpreterSuite.getRoot()).getPassedTestsCount(), + final int numberOfTests = new SMRootTestsCounter(interpreterSuite.getRoot()).getPassedTestsCount(); + Assert.assertThat(String.format("Not enough test passed, should %s at least", myMinimumSuccessTestCount), + numberOfTests, Matchers.greaterThanOrEqualTo(myMinimumSuccessTestCount)); + Assert.assertThat(String.format("Too many tests passed, should %s maximum", myMaximumSuccessTestCount), + numberOfTests, + Matchers.lessThanOrEqualTo(myMaximumSuccessTestCount)); // Check expected output final String message = String.format("Interpreter %s does not have expected string in output. \n ", interpreterName) + @@ -265,9 +285,6 @@ public final class PyToxTest extends PyEnvTestCase { } private static final class MyTestProcessRunner extends PyAbstractTestProcessRunner { - /** - * @param testPath testPath relative to community path - */ private MyTestProcessRunner() { super(PyToxConfigurationFactory.INSTANCE, PyToxConfiguration.class, 0); }