test history (initial)

This commit is contained in:
Anna Kozlova
2015-06-23 12:05:15 +03:00
parent a9a7c4cea9
commit 0a6fbb49fa
5 changed files with 281 additions and 10 deletions
@@ -0,0 +1,152 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.execution.testframework.sm.runner.history.actions;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.LabeledComponent;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.ui.*;
import com.intellij.ui.components.JBList;
import com.intellij.ui.components.JBRadioButton;
import com.intellij.ui.components.JBTextField;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
public class ImportTestResultsDialog extends DialogWrapper {
private final TextFieldWithBrowseButton myFileFieldComp;
private final JBTextField myHistorySizeField = new JBTextField();
private final JBList myList;
private final JRadioButton myFileRb = new JBRadioButton("From File:");
private final JRadioButton myHistoryRb = new JBRadioButton("From History:");
protected ImportTestResultsDialog(@Nullable Project project) {
super(project, false);
setTitle("Import Test Results");
final FileChooserDescriptor xmlDescriptor = FileChooserDescriptorFactory.createSingleFileDescriptor(StdFileTypes.XML);
myFileFieldComp = new TextFieldWithBrowseButton();
myFileFieldComp.addBrowseFolderListener("Choose a File with Tests Result", null, project, xmlDescriptor);
final DefaultListModel model = new DefaultListModel();
final String[] historyFiles = ImportTestsAction.TEST_HISTORY_PATH.list();
if (historyFiles != null) {
for (String fileName : historyFiles) {
model.addElement(fileName);
}
}
myList = new JBList(model);
myList.setSelectedIndex(0);
final ButtonGroup group = new ButtonGroup();
group.add(myFileRb);
group.add(myHistoryRb);
init();
}
@Nullable
@Override
protected JComponent createCenterPanel() {
final JPanel wholePanel = new JPanel(new BorderLayout());
final JPanel panelWithFileTextField = new JPanel(new BorderLayout());
panelWithFileTextField.add(myFileRb, BorderLayout.NORTH);
panelWithFileTextField.add(myFileFieldComp, BorderLayout.CENTER);
final JPanel panelWithHistory = new JPanel(new BorderLayout());
panelWithHistory.add(myHistoryRb, BorderLayout.NORTH);
final JPanel historyPanel = new JPanel(new BorderLayout());
final ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myList)
.disableUpAction()
.disableDownAction()
.disableAddAction()
.setRemoveAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
ListUtil.removeSelectedItems(myList);
}
});
historyPanel.add(decorator.createPanel(), BorderLayout.CENTER);
myHistorySizeField.setText(PropertiesComponent.getInstance().getValue(ImportTestsAction.TEST_HISTORY_SIZE, "5"));
final LabeledComponent<JBTextField> sizeComponent = new LabeledComponent<JBTextField>();
sizeComponent.setText("History size:");
sizeComponent.setComponent(myHistorySizeField);
sizeComponent.setLabelLocation(BorderLayout.WEST);
historyPanel.add(sizeComponent, BorderLayout.SOUTH);
panelWithHistory.add(historyPanel, BorderLayout.CENTER);
wholePanel.add(panelWithFileTextField, BorderLayout.NORTH);
wholePanel.add(panelWithHistory, BorderLayout.CENTER);
final ActionListener enableListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updateComponents(historyPanel);
}
};
myFileRb.addActionListener(enableListener);
myHistoryRb.addActionListener(enableListener);
final boolean hasHistory = !myList.isEmpty();
myFileRb.setSelected(!hasHistory);
myHistoryRb.setSelected(hasHistory);
updateComponents(historyPanel);
return wholePanel;
}
private void updateComponents(JPanel historyPanel) {
UIUtil.setEnabled(historyPanel, !myFileRb.isSelected(), true);
UIUtil.setEnabled(myFileFieldComp, !myHistoryRb.isSelected(), true);
}
@Override
protected void doOKAction() {
PropertiesComponent.getInstance().setValue(ImportTestsAction.TEST_HISTORY_SIZE, myHistorySizeField.getText().trim());
final String[] historyFiles = ImportTestsAction.TEST_HISTORY_PATH.list();
final DefaultListModel model = (DefaultListModel)myList.getModel();
final ArrayList<File> toDelete = new ArrayList<File>();
for (String fileName : historyFiles) {
if (!model.contains(fileName)) {
toDelete.add(new File(ImportTestsAction.TEST_HISTORY_PATH, fileName));
}
}
for (File file : toDelete) {
FileUtil.delete(file);
}
super.doOKAction();
}
@Nullable
public String getFilePath() {
return myFileRb.isSelected() ? myFileFieldComp.getText()
: FileUtil.toSystemIndependentName(ImportTestsAction.TEST_HISTORY_PATH.getPath()) + "/" + myList.getSelectedValue();
}
}
@@ -30,8 +30,10 @@ import com.intellij.execution.testframework.sm.runner.history.ImportedTestRunnab
import com.intellij.execution.testframework.sm.runner.SMRunnerConsolePropertiesProvider;
import com.intellij.execution.testframework.sm.runner.SMTRunnerConsoleProperties;
import com.intellij.icons.AllIcons;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
@@ -41,6 +43,8 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import org.jdom.Document;
@@ -49,6 +53,9 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.io.File;
import java.util.Arrays;
import java.util.Comparator;
/**
* 1. chooses file where test results were saved
@@ -59,6 +66,8 @@ import javax.swing.*;
*/
public class ImportTestsAction extends AnAction {
private static final Logger LOG = Logger.getInstance("#" + ImportTestsAction.class.getName());
public static final File TEST_HISTORY_PATH = new File(PathManager.getSystemPath(), "testHistory");
public static final String TEST_HISTORY_SIZE = "test_history_size";
private SMTRunnerConsoleProperties myProperties;
public ImportTestsAction() {
@@ -77,11 +86,17 @@ public class ImportTestsAction extends AnAction {
@Override
public void actionPerformed(AnActionEvent e) {
final FileChooserDescriptor xmlDescriptor = FileChooserDescriptorFactory.createSingleFileDescriptor(StdFileTypes.XML);
xmlDescriptor.setTitle("Choose a File with Tests Result");
final Project project = e.getProject();
LOG.assertTrue(project != null);
final VirtualFile file = FileChooser.chooseFile(xmlDescriptor, project, null);
final ImportTestResultsDialog dialog = new ImportTestResultsDialog(project);
if (!dialog.showAndGet()) {
return;
}
final String filePath = dialog.getFilePath();
if (filePath == null) {
return;
}
final VirtualFile file = LocalFileSystem.getInstance().findFileByPath(filePath);
if (file != null) {
try {
final ImportRunProfile profile = new ImportRunProfile(file, project);
@@ -100,6 +115,30 @@ public class ImportTestsAction extends AnAction {
}
}
}
public static void adjustHistory() {
int historySize;
try {
historySize = Math.max(0, Integer.parseInt(PropertiesComponent.getInstance().getValue(TEST_HISTORY_SIZE, "5")));
}
catch (NumberFormatException e) {
historySize = 5;
}
final File[] files = TEST_HISTORY_PATH.listFiles();
if (files != null && files.length >= historySize) {
Arrays.sort(files, new Comparator<File>() {
@Override
public int compare(File o1, File o2) {
final long l1 = o1.lastModified();
final long l2 = o2.lastModified();
if (l1 == l2) return 0;
return l1 < l2 ? -1 : 1;
}
});
FileUtil.delete(files[0]);
}
}
public static class ImportRunProfile implements RunProfile {
private final VirtualFile myFile;
@@ -15,24 +15,38 @@
*/
package com.intellij.execution.testframework.sm.runner.ui;
import com.intellij.execution.ExecutionBundle;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.testframework.*;
import com.intellij.execution.testframework.export.TestResultsXmlFormatter;
import com.intellij.execution.testframework.sm.SMRunnerUtil;
import com.intellij.execution.testframework.sm.runner.*;
import com.intellij.execution.testframework.sm.runner.history.ImportedTestConsoleProperties;
import com.intellij.execution.testframework.sm.runner.history.actions.ImportTestsAction;
import com.intellij.execution.testframework.sm.runner.ui.statistics.StatisticsPanel;
import com.intellij.execution.testframework.ui.TestResultsPanel;
import com.intellij.execution.testframework.ui.TestsProgressAnimator;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.progress.impl.BackgroundableProcessIndicator;
import com.intellij.openapi.progress.util.ColorProgressBar;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pass;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.JBColor;
import com.intellij.util.Alarm;
import com.intellij.util.PathUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.text.DateFormatUtil;
import com.intellij.util.ui.update.Update;
@@ -43,9 +57,18 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
@@ -57,6 +80,7 @@ public class SMTestRunnerResultsForm extends TestResultsPanel
@NonNls private static final String DEFAULT_SM_RUNNER_SPLITTER_PROPERTY = "SMTestRunner.Splitter.Proportion";
public static final Color DARK_YELLOW = JBColor.YELLOW.darker();
private static final Logger LOG = Logger.getInstance("#" + SMTestRunnerResultsForm.class.getName());
private SMTRunnerTestTreeView myTreeView;
@@ -91,6 +115,7 @@ public class SMTestRunnerResultsForm extends TestResultsPanel
private AbstractTestProxy myLastSelected;
private Alarm myUpdateQueue;
private Set<Update> myRequests = Collections.synchronizedSet(new HashSet<Update>());
private BackgroundableProcessIndicator mySaveToHistoryIndicator;
public SMTestRunnerResultsForm(@NotNull final JComponent console,
final TestConsoleProperties consoleProperties) {
@@ -303,6 +328,56 @@ public class SMTestRunnerResultsForm extends TestResultsPanel
final TestsUIUtil.TestResultPresentation presentation = new TestsUIUtil.TestResultPresentation(testsRoot, myStartTime > 0, null)
.getPresentation(myFailedTestCount, myFinishedTestCount - myFailedTestCount - myIgnoredTestCount, myTotalTestCount - myFinishedTestCount, myIgnoredTestCount);
TestsUIUtil.notifyByBalloon(myConsoleProperties.getProject(), testsRoot, myConsoleProperties, presentation);
addToHistory(testsRoot);
}
private void addToHistory(final SMTestProxy.SMRootTestProxy root) {
final RunProfile configuration = myConsoleProperties.getConfiguration();
if (configuration instanceof RunConfiguration && !(myConsoleProperties instanceof ImportedTestConsoleProperties)) {
final Task.Backgroundable backgroundable = new Task.Backgroundable(myProject, "Save Test Results", true) {
private String myOutput;
@Override
public void run(@NotNull ProgressIndicator indicator) {
try {
SAXTransformerFactory transformerFactory = (SAXTransformerFactory)TransformerFactory.newInstance();
TransformerHandler handler = transformerFactory.newTransformerHandler();
handler.getTransformer().setOutputProperty(OutputKeys.INDENT, "yes");
handler.getTransformer().setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
StringWriter w = new StringWriter();
handler.setResult(new StreamResult(w));
TestResultsXmlFormatter.execute(root, (RunConfiguration)configuration, handler);
myOutput = w.toString();
}
catch (ProcessCanceledException ignore) {
//canceled by user or frame dispose
}
catch (Exception e) {
LOG.info("Export to history failed", e);
}
}
@Override
public void onSuccess() {
if (myOutput != null) {
try {
ImportTestsAction.adjustHistory();
final String configurationNameIncludedDate = PathUtil.suggestFileName(configuration.getName()) + " " +
FileUtil.sanitizeFileName(new SimpleDateFormat().format(new Date()));
final String presentableFileName = ExecutionBundle.message("export.test.results.filename", configurationNameIncludedDate);
FileUtil.writeToFile(new File(ImportTestsAction.TEST_HISTORY_PATH, presentableFileName + ".xml"), myOutput);
}
catch (IOException e) {
LOG.info("Fail to write test history", e);
}
}
}
};
mySaveToHistoryIndicator = new BackgroundableProcessIndicator(backgroundable);
ProgressManager.getInstance().runProcessWithProgressAsynchronously(backgroundable, mySaveToHistoryIndicator);
}
}
public void onTestsCountInSuite(final int count) {
@@ -464,6 +539,9 @@ public class SMTestRunnerResultsForm extends TestResultsPanel
myShowStatisticForProxyHandler = null;
myEventListeners.clear();
myStatisticsPane.doDispose();
if (mySaveToHistoryIndicator != null) {
mySaveToHistoryIndicator.cancel();
}
}
public void showStatisticsForSelectedProxy() {
@@ -29,10 +29,7 @@ import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Attachment;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.progress.PerformInBackgroundOption;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.progress.*;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
@@ -309,7 +306,12 @@ public class ExportTestResultsAction extends DumbAwareAction {
StringWriter w = new StringWriter();
handler.setResult(new StreamResult(w));
TestResultsXmlFormatter.execute(myModel.getRoot(), myRunConfiguration, handler);
try {
TestResultsXmlFormatter.execute(myModel.getRoot(), myRunConfiguration, handler);
}
catch (ProcessCanceledException e) {
return null;
}
return w.toString();
}
@@ -16,7 +16,6 @@
package com.intellij.execution.testframework.export;
import com.intellij.execution.ExecutionBundle;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.filters.*;
import com.intellij.execution.impl.RunManagerImpl;
@@ -28,7 +27,7 @@ import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.text.StringUtil;
@@ -166,6 +165,7 @@ public class TestResultsXmlFormatter {
}
private void processNode(AbstractTestProxy node, final Filter filter) throws SAXException {
ProgressManager.checkCanceled();
Map<String, String> attrs = new HashMap<String, String>();
attrs.put(ATTR_NAME, node.getName());
attrs.put(ATTR_STATUS, getStatusString(node));