/** * Adds a set of arguments used to wrap executed file with unittest runner. * * @param actualRun in an actual run we'll start the xml-rpc server. * @param coverageRun whether we should add the flags to do a coverage run. */ private void addUnittestArgs(List<String> cmdArgs, boolean actualRun, boolean coverageRun) throws CoreException { if (isUnittest()) { // The tests are either written to a configuration file or passed as a parameter. String configurationFile = this.configuration.getAttribute(Constants.ATTR_UNITTEST_CONFIGURATION_FILE, ""); if (configurationFile.length() > 0) { cmdArgs.add("--config_file"); if (actualRun) { // We should write the contents to a temporary file (because it may be too long, so, // always write // to a file and read from it later on). File tempFile = PydevPlugin.getDefault().getTempFile("custom_pydev_unittest_launch_"); try { OutputStream fileOutputStream = new FileOutputStream(tempFile); try { try { fileOutputStream.write(configurationFile.getBytes()); } catch (IOException e) { throw new CoreException( PydevPlugin.makeStatus(IStatus.ERROR, "Error writing to: " + tempFile, e)); } } finally { fileOutputStream.close(); } } catch (Exception e) { if (e instanceof CoreException) { throw (CoreException) e; } throw new CoreException( PydevPlugin.makeStatus(IStatus.ERROR, "Error writing to: " + tempFile, e)); } cmdArgs.add(tempFile.toString()); } else { cmdArgs.add(configurationFile); } } else { String tests = this.configuration.getAttribute(Constants.ATTR_UNITTEST_TESTS, ""); if (tests.length() > 0) { cmdArgs.add("--tests"); cmdArgs.add(tests); } } if (PyUnitPrefsPage2.getUsePyUnitView()) { // If we want to use the PyUnitView, we need to get the port used so that the python side // can connect. cmdArgs.add("--port"); if (actualRun) { cmdArgs.add(String.valueOf(getPyUnitServer().getPort())); } else { cmdArgs.add("0"); } } if (coverageRun) { cmdArgs.add("--coverage_output_dir"); cmdArgs.add(PyCoverage.getCoverageDirLocation().getAbsolutePath()); cmdArgs.add("--coverage_include"); cmdArgs.add(PyCodeCoverageView.getChosenDir().getLocation().toOSString()); if (actualRun) { IPreferenceStore prefs = PydevPrefs.getPreferenceStore(); int testRunner = prefs.getInt(PyUnitPrefsPage2.TEST_RUNNER); switch (testRunner) { case PyUnitPrefsPage2.TEST_RUNNER_NOSE: RunInUiThread.async( new Runnable() { public void run() { PyDialogHelpers.openWarningWithIgnoreToggle( "Notes for coverage with the nose test runner.", "Note1: When using the coverage with the nose test runner, " + "please don't pass any specific parameter related to " + "the run in the arguments, as that's already handled by PyDev " + "(i.e.: don't use the builtin cover plugin from nose).\n" + "\n" + "Note2: It's currently not possible to use coverage with the multi-process " + "plugin in nose.", "KEY_COVERAGE_WITH_NOSE_TEST_RUNNER"); } }); break; case PyUnitPrefsPage2.TEST_RUNNER_PY_TEST: RunInUiThread.async( new Runnable() { public void run() { PyDialogHelpers.openCritical( "PyUnit coverage not compatible with the Py.test test runner.", "Currently the PyDev PyUnit integration is not able to provide coverage " + "info using the py.test test runner (please enter a " + "feature request if you'd like that added)\n" + "\n" + "Note: the run will be continued anyways (without gathering coverage info)."); } }); break; } } } // Last thing: nose parameters or parameters the user configured. for (String s : parseStringIntoList( PyUnitPrefsPage2.getTestRunnerParameters(this.configuration, this.project))) { cmdArgs.add(s); } } }
/** * Create a command line for launching. * * @param actualRun if true it'll make the variable substitution and start the listen connector in * the case of a debug session. * @return command line ready to be exec'd * @throws CoreException * @throws JDTNotAvailableException */ public String[] getCommandLine(boolean actualRun) throws CoreException, JDTNotAvailableException { List<String> cmdArgs = new ArrayList<String>(); if (isJython()) { // "java.exe" -classpath "C:\bin\jython21\jython.jar" org.python.util.jython script %ARGS% String javaLoc = JavaVmLocationFinder.findDefaultJavaExecutable().getAbsolutePath(); if (!InterpreterInfo.isJythonExecutable(interpreter.toOSString())) { throw new RuntimeException( "The jython jar must be specified as the interpreter to run. Found: " + interpreter); } cmdArgs.add(javaLoc); // some nice things on the classpath config: http://mindprod.com/jgloss/classpath.html cmdArgs.add("-classpath"); String cpath; // TODO: add some option in the project so that the user can choose to use the // classpath specified in the java project instead of the pythonpath itself // if (project.getNature(Constants.JAVA_NATURE) != null){ // cpath = getClasspath(JavaCore.create(project)); // } else { cpath = interpreter + SimpleRunner.getPythonPathSeparator() + pythonpathUsed; // } cmdArgs.add(cpath); cmdArgs.add( "-Dpython.path=" + pythonpathUsed); // will be added to the env variables in the run (check if this // works on all platforms...) addVmArgs(cmdArgs); if (isDebug) { // This was removed because it cannot be used. See: // http://bugs.jython.org/issue1438 // cmdArgs.add("-Dpython.security.respectJavaAccessibility=false"); cmdArgs.add("org.python.util.jython"); addDebugArgs(cmdArgs, "jython", actualRun); } else { cmdArgs.add("org.python.util.jython"); } } else { // python or iron python cmdArgs.add(interpreter.toOSString()); // Next option is for unbuffered stdout, otherwise Eclipse will not see any output until done cmdArgs.add("-u"); addVmArgs(cmdArgs); if (isDebug && isIronpython()) { addIronPythonDebugVmArgs(cmdArgs); } addDebugArgs(cmdArgs, "python", actualRun); } // Check if we should do code-coverage... boolean coverageRun = PyCoveragePreferences.getAllRunsDoCoverage(); if (coverageRun && isDebug) { if (actualRun) { RunInUiThread.async( new Runnable() { public void run() { PyDialogHelpers.openWarning( "Conflicting options: coverage with debug.", "Making a debug run with coverage enabled will not yield the expected results.\n\n" + "They'll conflict because both use the python tracing facility (i.e.: sys.settrace()).\n" + "\n" + "To debug a coverage run, do a regular run and use the remote debugger " + "(but note that the coverage will stop when it's enabled).\n" + "\n" + "Note: the run will be continued anyways."); } }); } } if (isUnittest()) { cmdArgs.add(getRunFilesScript()); } else { if (coverageRun) { // Separate support (unittest has the coverage support builtin). cmdArgs.add(getCoverageScript()); cmdArgs.add(PyCoverage.getCoverageFileLocation().getAbsolutePath()); cmdArgs.add("run"); cmdArgs.add("--source"); cmdArgs.add(PyCodeCoverageView.getChosenDir().getLocation().toOSString()); } } for (IPath p : resource) { cmdArgs.add(p.toOSString()); } if (!isUnittest()) { // The program arguments are not used when running a unittest (excluded from the tab group in // favor // of a way to overriding the default unittest arguments). String runArguments[] = null; if (actualRun && arguments != null) { String expanded = getStringSubstitution(PythonNature.getPythonNature(project)) .performStringSubstitution(arguments); runArguments = parseStringIntoList(expanded); } for (int i = 0; runArguments != null && i < runArguments.length; i++) { cmdArgs.add(runArguments[i]); } } else { // Last thing (first the files and last the special parameters the user passed -- i.e.: nose // parameters) addUnittestArgs(cmdArgs, actualRun, coverageRun); } String[] retVal = new String[cmdArgs.size()]; cmdArgs.toArray(retVal); if (actualRun) { CreatedCommandLineParams createdCommandLineParams = new CreatedCommandLineParams(retVal, coverageRun); // Provide a way for clients to alter the command line. List<Object> participants = ExtensionHelper.getParticipants(ExtensionHelper.PYDEV_COMMAND_LINE_PARTICIPANT); for (Object object : participants) { try { IPyCommandLineParticipant c = (IPyCommandLineParticipant) object; createdCommandLineParams = c.updateCommandLine(createdCommandLineParams); } catch (Exception e) { Log.log(e); } } retVal = createdCommandLineParams.cmdLine; PythonRunnerCallbacks.onCreatedCommandLine.call(createdCommandLineParams); } return retVal; }