470cd7f2134e27f0546783815e16cd39f453677e
[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     final String workingDirectory = myConfiguration.getWorkingDirectory();
107     if (!StringUtil.isEmptyOrSpaces(workingDirectory)) {
108       cmd.withWorkDirectory(workingDirectory);
109     }
110     else if (myConfiguration instanceof AbstractPythonTestRunConfiguration) {
111       final AbstractPythonTestRunConfiguration configuration = (AbstractPythonTestRunConfiguration)myConfiguration;
112       cmd.withWorkDirectory(configuration.getWorkingDirectorySafe());
113     }
114   }
115
116   @Override
117   public ExecutionResult execute(Executor executor, CommandLinePatcher... patchers) throws ExecutionException {
118     final ProcessHandler processHandler = startProcess(patchers);
119     final ConsoleView console = createAndAttachConsole(myConfiguration.getProject(), processHandler, executor);
120
121     List<AnAction> actions = Lists
122       .newArrayList(createActions(console, processHandler));
123
124     DefaultExecutionResult executionResult =
125       new DefaultExecutionResult(console, processHandler, actions.toArray(new AnAction[actions.size()]));
126
127     PyRerunFailedTestsAction rerunFailedTestsAction = new PyRerunFailedTestsAction(console);
128     if (console instanceof SMTRunnerConsoleView) {
129       rerunFailedTestsAction.init(((BaseTestsOutputConsoleView)console).getProperties());
130       rerunFailedTestsAction.setModelProvider(() -> ((SMTRunnerConsoleView)console).getResultsViewer());
131     }
132
133     executionResult.setRestartActions(rerunFailedTestsAction, new ToggleAutoTestAction());
134     return executionResult;
135   }
136
137   protected void addBeforeParameters(GeneralCommandLine cmd)  {}
138   protected void addAfterParameters(GeneralCommandLine cmd) {}
139
140   protected void addTestRunnerParameters(GeneralCommandLine cmd)  {
141     ParamsGroup scriptParams = cmd.getParametersList().getParamsGroup(GROUP_SCRIPT);
142     assert scriptParams != null;
143     getRunner().addToGroup(scriptParams, cmd);
144     addBeforeParameters(cmd);
145     myConfiguration.addTestSpecsAsParameters(scriptParams, getTestSpecs());
146     addAfterParameters(cmd);
147   }
148
149   @Override
150   public void customizeEnvironmentVars(Map<String, String> envs, boolean passParentEnvs) {
151     super.customizeEnvironmentVars(envs, passParentEnvs);
152     envs.put("PYCHARM_HELPERS_DIR", PythonHelpersLocator.getHelperPath("pycharm"));
153   }
154
155   protected abstract HelperPackage getRunner();
156   @NotNull
157   protected abstract List<String> getTestSpecs();
158 }