better support
"""
import os
-import sys
from tox import config as tox_config, session as tox_session
-from tox.session import Reporter
from tcmessages import TeamcityServiceMessages
+from tox import exception
+
+teamcity = TeamcityServiceMessages()
helpers_dir = str(os.path.split(__file__)[0])
+class _MySession(tox_session.Session):
+ """
+ Session is extended to overwrite "setupenv" as "env begin" ans "_summary" as "end of all"
+ Hooks API is not enough to cover each case, reporter is not enough as well
+ Session inheritance is the only way to go, even it is not stable and should be checked
+ against each version
+ """
+
+ def __init__(self, *args, **kwargs):
+ tox_session.Session.__init__(self, *args, **kwargs)
+ self.current_env = None
+
+ def setupenv(self, venv):
+ """
+ Launched before each setup.
+ It means prev env (if any) just finished and new is going to be created
+ :param venv: current virtual env
+ """
+ self._finish_current_env_if_need()
+ self.current_env = venv
+ teamcity.testSuiteStarted(venv.name, location="tox_env://" + str(venv.name))
+ return tox_session.Session.setupenv(self, venv)
+
+ def _finish_current_env_if_need(self):
+ """
+ Finishes currently running env. reporting its state
+ """
+ if not self.current_env:
+ return
+
+ status = self.current_env.status
+ if isinstance(status, exception.InterpreterNotFound):
+ if self.config.option.skip_missing_interpreters:
+ self._reportSuiteStateLeaf("SKIP", status)
+ else:
+ self._reportSuiteStateLeaf("ERROR", status)
+ elif status == "platform mismatch":
+ self._reportSuiteStateLeaf("SKIP", status)
+ elif status and status == "ignored failed command":
+ print(" %s: %s" % (self.current_env.name, str(status)))
+ elif status and status != "skipped tests":
+ self._reportSuiteStateLeaf("ERROR", status)
+ teamcity.testStdOut(self.current_env.name, "\n")
+ teamcity.testSuiteFinished(self.current_env.name)
+ self.current_env = None
+
+ def _reportSuiteStateLeaf(self, state, message):
+ """
+ Since platform does not support empty suite, we need to output something.
+ :param state: SKIP or ERROR (suite result)
+ """
+ teamcity.testStarted(state, "tox_env://" + str(self.current_env.name))
+ if state == "SKIP":
+ teamcity.testIgnored(state, str(message))
+ else:
+ teamcity.testFailed(state, str(message))
+
+ def _summary(self):
+ """
+ To be called after whole suite.
+ """
+ self._finish_current_env_if_need()
+
+
class _Unit2(object):
def fix(self, command, dir_to_run, bin):
if command[0] == "unit2":
return [bin, os.path.join(helpers_dir, "noserunner.py"), dir_to_run] + command[1:]
-
_RUNNERS = [_Unit2(), _PyTest(), _Nose()]
-teamcity = TeamcityServiceMessages()
-
-
-class _Reporter(Reporter):
- def logaction_start(self, action):
- super(_Reporter, self).logaction_start(action)
- if action.activity == "getenv":
- teamcity.output.write("\n")
- teamcity.testSuiteStarted(action.id, location="tox_env://" + str(action.id))
- self.current_suite = action.id
-
- def logaction_finish(self, action):
- super(_Reporter, self).logaction_finish(action)
- if action.activity == "runtests":
- teamcity.testSuiteFinished(action.id)
- teamcity.output.write("\n")
-
- def error(self, msg):
- super(_Reporter, self).error(msg)
- name = teamcity.current_test_name()
- if name:
- if name != teamcity.topmost_suite:
- teamcity.testFailed(name, msg)
- else:
- teamcity.testFailed("ERROR", msg)
- teamcity.testSuiteFinished(name)
- else:
- sys.stderr.write(msg)
-
- def skip(self, msg):
- super(_Reporter, self).skip(msg)
- name = teamcity.current_test_name()
- if name:
- teamcity.testFinished(name)
-
-
config = tox_config.parseconfig()
for env, tmp_config in config.envconfigs.items():
if not tmp_config.setenv:
_env = config.envconfigs[env]
dir_to_run = str(_env.changedir)
for i, command in enumerate(commands):
- fixed_command = fixer.fix(command, dir_to_run, str(_env.envpython))
- if fixed_command:
- commands[i] = fixed_command
+ if command:
+ fixed_command = fixer.fix(command, dir_to_run, str(_env.envpython))
+ if fixed_command:
+ commands[i] = fixed_command
tmp_config.commands = commands
-session = tox_session.Session(config, Report=_Reporter)
+session = _MySession(config)
teamcity.testMatrixEntered()
session.runcommand()
);
}
+ /**
+ * Checks empty envs for all but 2.7
+ */
+ @Test
+ public void textToxOneInterpreter() throws Exception {
+ runPythonTest(new MyPyProcessWithConsoleTestTask("/toxtest/toxOneInterpreter/", 0,
+ new MyTestProcessRunner(),
+ Arrays.asList(
+ Pair.create("py26", new InterpreterExpectations("", true)),
+ Pair.create("py27", new InterpreterExpectations("ython 2.7", true)),
+ Pair.create("py32", new InterpreterExpectations("", true)),
+ Pair.create("py34", new InterpreterExpectations("", true))
+ )
+ )
+ );
+
+
+ }
+
/**
* Big test which should run on any interpreter and check its output
*/
// Interpreter failed to run
final String testOutput = getTestOutput(interpreterSuite.getChildren().get(0));
if (testOutput.contains("InterpreterNotFound")) {
+ // Skipped with out of "skip_missing_interpreters = True"
Logger.getInstance(PyToxTest.class).warn(String.format("Interpreter %s does not exit", interpreterName));
skippedInterpreters.add(interpreterName); // Interpreter does not exit
continue;
continue;
}
+ 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"));
+ }
+
+
// Interpretr run success,
//At least one interpreter tests should passed
Assert.assertThat(String.format("No test passed, should %s at least", myMinimumSuccessTestCount),