Reading unit test run configuration

Answered

I'm writing a PyCharm plugin, and I want to read some details from the currently selected run configuration, particularly if it's a unit test. I use these details to launch a process that runs a modified version of the test and displays the result.

I had this working for an earlier version of PyCharm (build 171.4694), but it broke with the update to version 2017.2. Here's how I'm currently reading the working directory, SDK home, and test target:

import com.jetbrains.python.testing.universalTests.PyUniversalUnitTestConfiguration;
...
} else if (runConfiguration instanceof PyUniversalUnitTestConfiguration) {
PyUniversalUnitTestConfiguration unitTestConfiguration =
(PyUniversalUnitTestConfiguration) runConfiguration;
workingDir = unitTestConfiguration.getWorkingDirectory();
processArguments = Lists.newArrayList(
unitTestConfiguration.getSdkHome(),
"-m",
"code_tracer");
processArguments.add("-"); // source code from stdin
String moduleName = getModuleName(
new File(mainFile.getPath()),
workingDir);
processArguments.add(moduleName);
processArguments.add("-m");
processArguments.add("unittest");
processArguments.add(unitTestConfiguration.getTarget().getTarget());

Unfortunately, the whole `universalTests` package has disappeared in the new version, and I get a `NoClassDefFoundError`.

com/jetbrains/python/testing/universalTests/PyUniversalUnitTestConfiguration
java.lang.NoClassDefFoundError: com/jetbrains/python/testing/universalTests/PyUniversalUnitTestConfiguration
at io.github.donkirkby.livepycharm.SplitFileEditor.<init>(SplitFileEditor.java:52)
at io.github.donkirkby.livepycharm.SplitFileEditorProvider.createSplitEditor(SplitFileEditorProvider.java:179)
at io.github.donkirkby.livepycharm.SplitFileEditorProvider.access$200(SplitFileEditorProvider.java:22)
at io.github.donkirkby.livepycharm.SplitFileEditorProvider$1.build(SplitFileEditorProvider.java:100)
at com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl.lambda$openFileImpl4$8(FileEditorManagerImpl.java:860)


Is there some more-supported method for getting the details of a run configuration? I tried to step through the process launch and the command line state classes, but I can't follow it. Am I going to get in trouble for starting my own process in the first place without going through IntelliJ's executor?

Do I have to resort to reflection or some other horror? My best guess right now is to use the writeExternal() method to convert the configuration to an XML DOM, and then dig through that. I hope there's an easier way, though.

6 comments
Comment actions Permalink
Official comment

Hello.

PyCharm test runners are not part of public api and subject to change in any minor update. They are currently moved to PyTestsShared.kt (PyAbstractTestConfiguration).

 

It is better to create custom runner: https://confluence.jetbrains.com/display/~link/Custom+test+runner+example

Comment actions Permalink

Thanks, Ilya, I'll check out the custom runner.

How can I tell what's part of the public API?

0
Comment actions Permalink

Hello.

We are currently working on document to cover this topic.

There are Platform Open API modules. No public symbol in these modules can be removed without of been deprecated for several releases before that.

See PLATFORM_API_MODULES  https://github.com/JetBrains/intellij-community/blob/master/platform/build-scripts/groovy/org/jetbrains/intellij/build/CommunityRepositoryModules.groovy for list of modules.

python-psi-api and python-openapi modules are also public API and considered stable.

 

Unfortunatelly, not all classes from example above are part of Open API for now, but they are mature and probably would not be changed. We will publish separate document about special "custom test-runner API" as it becomes ready.

1
Comment actions Permalink

Thanks for the explanation, Ilya. As an example, this post recommended that I use the Alarm class, but it's in the com.intellij.util package. That's not listed in the CommunityRepositoryModules.groovy file you mentioned, so should I not use it?

0
Comment actions Permalink

Package does not play any role here.  Alarm is in ``platform-api`` module which is mentioned in ``CommunityRepositoryModules#PLATFORM_API_MODULES ``, so you can use it.

0
Comment actions Permalink

Here's an update on my original question, in case someone else is trying to do the same thing. I ended up creating a command line patcher like this:

commandLinePatcher = commandLine -> {
Map<String, String> environment1 = commandLine.getEnvironment();
ParamsGroup paramsGroup = commandLine.getParametersList().getParamsGroup(
PythonCommandLineState.GROUP_SCRIPT);
int i = 0;
paramsGroup.addParameterAt(i++, "-m");
paramsGroup.addParameterAt(i++, "code_tracer");
};

Then I used it to adjust the command line generated by the run configuration before starting the process:

final GeneralCommandLine commandLine = commandLineState.generateCommandLine(
new CommandLinePatcher[]{commandLinePatcher});
final CapturingProcessHandler processHandler = new CapturingProcessHandler(commandLine);

 

0

Please sign in to leave a comment.