PY-21454: Use project dir if directory not provided
[idea/community.git] / python / src / com / jetbrains / python / testing / PythonTestCommandLineStateBase.java
1 /*
2  * Copyright 2000-2015 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.jetbrains.python.testing;
17
18 import com.google.common.collect.Lists;
19 import com.intellij.execution.DefaultExecutionResult;
20 import com.intellij.execution.ExecutionException;
21 import com.intellij.execution.ExecutionResult;
22 import com.intellij.execution.Executor;
23 import com.intellij.execution.configurations.GeneralCommandLine;
24 import com.intellij.execution.configurations.ParamsGroup;
25 import com.intellij.execution.process.ProcessHandler;
26 import com.intellij.execution.runners.ExecutionEnvironment;
27 import com.intellij.execution.testframework.autotest.ToggleAutoTestAction;
28 import com.intellij.execution.testframework.sm.SMTestRunnerConnectionUtil;
29 import com.intellij.execution.testframework.sm.runner.ui.SMTRunnerConsoleView;
30 import com.intellij.execution.testframework.ui.BaseTestsOutputConsoleView;
31 import com.intellij.execution.ui.ConsoleView;
32 import com.intellij.openapi.actionSystem.AnAction;
33 import com.intellij.openapi.project.Project;
34 import com.intellij.openapi.util.text.StringUtil;
35 import com.jetbrains.python.HelperPackage;
36 import com.jetbrains.python.PythonHelpersLocator;
37 import com.jetbrains.python.console.PythonDebugLanguageConsoleView;
38 import com.jetbrains.python.run.AbstractPythonRunConfiguration;
39 import com.jetbrains.python.run.CommandLinePatcher;
40 import com.jetbrains.python.run.PythonCommandLineState;
41 import com.jetbrains.python.sdk.PythonSdkType;
42 import org.jetbrains.annotations.NotNull;
43
44 import java.util.List;
45 import java.util.Map;
46
47 /**
48  * @author yole
49  */
50 public abstract class PythonTestCommandLineStateBase extends PythonCommandLineState {
51   protected final AbstractPythonRunConfiguration myConfiguration;
52
53   public AbstractPythonRunConfiguration<?> getConfiguration() {
54     return myConfiguration;
55   }
56
57   public PythonTestCommandLineStateBase(AbstractPythonRunConfiguration configuration, ExecutionEnvironment env) {
58     super(configuration, env);
59     myConfiguration = configuration;
60     setRunWithPty(false);
61   }
62
63   @Override
64   @NotNull
65   protected ConsoleView createAndAttachConsole(Project project, ProcessHandler processHandler, Executor executor)
66     throws ExecutionException {
67
68     final PythonTRunnerConsoleProperties consoleProperties = createConsoleProperties(executor);
69
70     if (isDebug()) {
71       final ConsoleView testsOutputConsoleView = SMTestRunnerConnectionUtil.createConsole(PythonTRunnerConsoleProperties.FRAMEWORK_NAME,
72                                                                                           consoleProperties);
73       final ConsoleView consoleView =
74         new PythonDebugLanguageConsoleView(project, PythonSdkType.findSdkByPath(myConfiguration.getInterpreterPath()),
75                                            testsOutputConsoleView);
76       consoleView.attachToProcess(processHandler);
77       addTracebackFilter(project, consoleView, processHandler);
78       return consoleView;
79     }
80     final ConsoleView consoleView = SMTestRunnerConnectionUtil.createAndAttachConsole(PythonTRunnerConsoleProperties.FRAMEWORK_NAME,
81                                                                                       processHandler,
82                                                                                       consoleProperties);
83     addTracebackFilter(project, consoleView, processHandler);
84     return consoleView;
85   }
86
87   protected PythonTRunnerConsoleProperties createConsoleProperties(Executor executor) {
88     return new PythonTRunnerConsoleProperties(myConfiguration, executor, false);
89   }
90
91   @Override
92   public GeneralCommandLine generateCommandLine() {
93     GeneralCommandLine cmd = super.generateCommandLine();
94
95     setWorkingDirectory(cmd);
96
97     ParamsGroup exe_options = cmd.getParametersList().getParamsGroup(GROUP_EXE_OPTIONS);
98     assert exe_options != null;
99     exe_options.addParametersString(myConfiguration.getInterpreterOptions());
100     addTestRunnerParameters(cmd);
101
102     return cmd;
103   }
104
105   protected void setWorkingDirectory(@NotNull final GeneralCommandLine cmd) {
106     String workingDirectory = myConfiguration.getWorkingDirectory();
107     if (StringUtil.isEmptyOrSpaces(workingDirectory)) {
108       workingDirectory = myConfiguration.getWorkingDirectorySafe();
109     }
110     cmd.withWorkDirectory(workingDirectory);
111   }
112
113   @Override
114   public ExecutionResult execute(Executor executor, CommandLinePatcher... patchers) throws ExecutionException {
115     final ProcessHandler processHandler = startProcess(patchers);
116     final ConsoleView console = createAndAttachConsole(myConfiguration.getProject(), processHandler, executor);
117
118     List<AnAction> actions = Lists
119       .newArrayList(createActions(console, processHandler));
120
121     DefaultExecutionResult executionResult =
122       new DefaultExecutionResult(console, processHandler, actions.toArray(new AnAction[actions.size()]));
123
124     PyRerunFailedTestsAction rerunFailedTestsAction = new PyRerunFailedTestsAction(console);
125     if (console instanceof SMTRunnerConsoleView) {
126       rerunFailedTestsAction.init(((BaseTestsOutputConsoleView)console).getProperties());
127       rerunFailedTestsAction.setModelProvider(() -> ((SMTRunnerConsoleView)console).getResultsViewer());
128     }
129
130     executionResult.setRestartActions(rerunFailedTestsAction, new ToggleAutoTestAction());
131     return executionResult;
132   }
133
134   protected void addBeforeParameters(GeneralCommandLine cmd) {}
135
136   protected void addAfterParameters(GeneralCommandLine cmd) {}
137
138   protected void addTestRunnerParameters(GeneralCommandLine cmd) {
139     ParamsGroup scriptParams = cmd.getParametersList().getParamsGroup(GROUP_SCRIPT);
140     assert scriptParams != null;
141     getRunner().addToGroup(scriptParams, cmd);
142     addBeforeParameters(cmd);
143     myConfiguration.addTestSpecsAsParameters(scriptParams, getTestSpecs());
144     addAfterParameters(cmd);
145   }
146
147   @Override
148   public void customizeEnvironmentVars(Map<String, String> envs, boolean passParentEnvs) {
149     super.customizeEnvironmentVars(envs, passParentEnvs);
150     envs.put("PYCHARM_HELPERS_DIR", PythonHelpersLocator.getHelperPath("pycharm"));
151   }
152
153   protected abstract HelperPackage getRunner();
154
155   @NotNull
156   protected abstract List<String> getTestSpecs();
157 }