70 changed files with 612 additions and 3958 deletions
@ -1,546 +0,0 @@
@@ -1,546 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Diagnostics; |
||||
using System.IO; |
||||
using System.Linq; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.NRefactory.Utils; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Commands; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using ICSharpCode.SharpDevelop.Project.Commands; |
||||
using ICSharpCode.SharpDevelop.Util; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public abstract class AbstractRunTestCommand : AbstractMenuCommand |
||||
{ |
||||
static MessageViewCategory testRunnerCategory; |
||||
static AbstractRunTestCommand runningTestCommand; |
||||
List<IProject> projects; |
||||
IProject currentProject; |
||||
TestResultsMonitor testResultsMonitor; |
||||
|
||||
public AbstractRunTestCommand() |
||||
{ |
||||
testResultsMonitor = new TestResultsMonitor(); |
||||
testResultsMonitor.TestFinished += TestFinished; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the running test command.
|
||||
/// </summary>
|
||||
public static AbstractRunTestCommand RunningTestCommand { |
||||
get { |
||||
return runningTestCommand; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets whether a test is currently running.
|
||||
/// </summary>
|
||||
public static bool IsRunningTest { |
||||
get { |
||||
return runningTestCommand != null; |
||||
} |
||||
} |
||||
|
||||
public override void Run() |
||||
{ |
||||
projects = new List<IProject>(); |
||||
|
||||
IMethod m = TestableCondition.GetMethod(Owner); |
||||
ITypeDefinition c = (m != null) ? m.DeclaringType.GetDefinition() : TestableCondition.GetClass(Owner); |
||||
IProject project = TestableCondition.GetProject(Owner); |
||||
string namespaceFilter = TestableCondition.GetNamespace(Owner); |
||||
|
||||
if (project != null) { |
||||
projects.Add(project); |
||||
} else if (UnitTestsPad.Instance != null) { |
||||
projects.AddRange(UnitTestsPad.Instance.GetProjects()); |
||||
} |
||||
|
||||
if (projects.Count > 0) { |
||||
runningTestCommand = this; |
||||
try { |
||||
BeforeRun(); |
||||
if (IsRunningTest) { |
||||
currentProject = projects[0]; |
||||
Run(currentProject, namespaceFilter, c, m); |
||||
} |
||||
} catch { |
||||
runningTestCommand = null; |
||||
throw; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public static MessageViewCategory TestRunnerCategory { |
||||
get { |
||||
if (testRunnerCategory == null) { |
||||
MessageViewCategory.Create(ref testRunnerCategory, "UnitTesting", "${res:ICSharpCode.NUnitPad.NUnitPadContent.PadName}"); |
||||
} |
||||
return testRunnerCategory; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Stops running the tests.
|
||||
/// </summary>
|
||||
public void Stop() |
||||
{ |
||||
runningTestCommand = null; |
||||
UpdateUnitTestsPadToolbar(); |
||||
|
||||
projects.Clear(); |
||||
|
||||
testResultsMonitor.Stop(); |
||||
StopMonitoring(); |
||||
|
||||
OnStop(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Called before all tests are run. If multiple projects are
|
||||
/// to be tested this is called only once.
|
||||
/// </summary>
|
||||
protected virtual void OnBeforeRunTests() |
||||
{ |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Called after all tests have been run even if there have
|
||||
/// been errors. If multiple projects are to be tested this is called only once.
|
||||
/// </summary>
|
||||
protected virtual void OnAfterRunTests() |
||||
{ |
||||
} |
||||
|
||||
protected abstract void RunTests(UnitTestApplicationStartHelper helper); |
||||
|
||||
/// <summary>
|
||||
/// Called by derived classes when a single test run
|
||||
/// is finished.
|
||||
/// </summary>
|
||||
protected void TestsFinished() |
||||
{ |
||||
WorkbenchSingleton.AssertMainThread(); |
||||
|
||||
// Read the rest of the file just in case.
|
||||
testResultsMonitor.Stop(); |
||||
testResultsMonitor.Read(); |
||||
StopMonitoring(); |
||||
|
||||
projects.Remove(currentProject); |
||||
if (projects.Count > 0) { |
||||
currentProject = projects[0]; |
||||
Run(currentProject, null, null, null); |
||||
} else { |
||||
runningTestCommand = null; |
||||
UpdateUnitTestsPadToolbar(); |
||||
if (TaskService.SomethingWentWrong && ErrorListPad.ShowAfterBuild) { |
||||
ShowErrorList(); |
||||
} |
||||
OnAfterRunTests(); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Called by derived classes to show a single test result.
|
||||
/// </summary>
|
||||
protected void ShowResult(TestResult result) |
||||
{ |
||||
if (result.IsFailure || result.IsIgnored) { |
||||
TaskService.Add(CreateTask(result)); |
||||
} |
||||
UpdateTestResult(result); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Called when the test run should be stopped.
|
||||
/// </summary>
|
||||
protected virtual void OnStop() |
||||
{ |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Brings the specified pad to the front.
|
||||
/// </summary>
|
||||
protected void ShowPad(PadDescriptor padDescriptor) |
||||
{ |
||||
if (padDescriptor != null) { |
||||
WorkbenchSingleton.SafeThreadAsyncCall(padDescriptor.BringPadToFront); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Runs the tests after building the project under test.
|
||||
/// </summary>
|
||||
void Run(IProject project, string namespaceFilter, ITypeDefinition fixture, IMethod test) |
||||
{ |
||||
BuildProjectBeforeTestRun build = new BuildProjectBeforeTestRun(project); |
||||
build.BuildComplete += delegate { |
||||
OnBuildComplete(build.LastBuildResults, project, namespaceFilter, fixture, test); |
||||
}; |
||||
build.Run(); |
||||
} |
||||
|
||||
void ShowUnitTestsPad() |
||||
{ |
||||
ShowPad(WorkbenchSingleton.Workbench.GetPad(typeof(UnitTestsPad))); |
||||
} |
||||
|
||||
void UpdateUnitTestsPadToolbar() |
||||
{ |
||||
if (UnitTestsPad.Instance != null) { |
||||
UnitTestsPad.Instance.UpdateToolbar(); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Sets the initial workbench state before starting
|
||||
/// a test run.
|
||||
/// </summary>
|
||||
void BeforeRun() |
||||
{ |
||||
TaskService.BuildMessageViewCategory.ClearText(); |
||||
TaskService.InUpdate = true; |
||||
TaskService.ClearExceptCommentTasks(); |
||||
TaskService.InUpdate = false; |
||||
|
||||
TestRunnerCategory.ClearText(); |
||||
|
||||
ShowUnitTestsPad(); |
||||
ShowOutputPad(); |
||||
|
||||
UpdateUnitTestsPadToolbar(); |
||||
ResetAllTestResults(); |
||||
|
||||
OnBeforeRunTests(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Brings output pad to the front.
|
||||
/// </summary>
|
||||
void ShowOutputPad() |
||||
{ |
||||
ShowPad(WorkbenchSingleton.Workbench.GetPad(typeof(CompilerMessageView))); |
||||
} |
||||
|
||||
SDTask CreateTask(TestResult result) |
||||
{ |
||||
TaskType taskType = TaskType.Warning; |
||||
FileLineReference lineRef = null; |
||||
string message = String.Empty; |
||||
|
||||
if (result.IsFailure) { |
||||
taskType = TaskType.Error; |
||||
lineRef = OutputTextLineParser.GetNUnitOutputFileLineReference(result.StackTrace, true); |
||||
message = GetTestResultMessage(result, "${res:NUnitPad.NUnitPadContent.TestTreeView.TestFailedMessage}"); |
||||
} else if (result.IsIgnored) { |
||||
message = GetTestResultMessage(result, "${res:NUnitPad.NUnitPadContent.TestTreeView.TestNotExecutedMessage}"); |
||||
} |
||||
if (lineRef == null) { |
||||
lineRef = FindTest(result.Name); |
||||
} |
||||
if (lineRef != null) { |
||||
return new SDTask(FileName.Create(lineRef.FileName), |
||||
message, lineRef.Column, lineRef.Line, taskType); |
||||
} |
||||
return new SDTask(null, message, 0, 0, taskType); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Returns the test result message if there is on otherwise
|
||||
/// uses the string resource to create a message.
|
||||
/// </summary>
|
||||
string GetTestResultMessage(TestResult result, string stringResource) |
||||
{ |
||||
if (result.Message.Length > 0) { |
||||
return result.Message; |
||||
} |
||||
return StringParser.Parse(stringResource, new[] { new StringTagPair("TestCase", result.Name) }); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Returns the location of the specified test method in the
|
||||
/// project being tested.
|
||||
/// </summary>
|
||||
FileLineReference FindTest(string methodName) |
||||
{ |
||||
TestProject testProject = GetTestProject(currentProject); |
||||
if (testProject != null) { |
||||
TestMember method = testProject.GetTestMethod(methodName); |
||||
if (method != null) { |
||||
var filePos = method.Method.Region; |
||||
return new FileLineReference(filePos.FileName, filePos.BeginLine, filePos.BeginColumn); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
void ShowErrorList() |
||||
{ |
||||
ShowPad(WorkbenchSingleton.Workbench.GetPad(typeof(ErrorListPad))); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Runs the test for the project after a successful build.
|
||||
/// </summary>
|
||||
void OnBuildComplete(BuildResults results, IProject project, string namespaceFilter, ITypeDefinition fixture, IMethod test) |
||||
{ |
||||
if (results.ErrorCount == 0 && IsRunningTest) { |
||||
UnitTestApplicationStartHelper helper = new UnitTestApplicationStartHelper(); |
||||
|
||||
UnitTestingOptions options = UnitTestingOptions.Instance; |
||||
helper.NoThread = options.NoThread; |
||||
helper.NoLogo = options.NoLogo; |
||||
helper.NoDots = options.NoDots; |
||||
helper.Labels = options.Labels; |
||||
helper.ShadowCopy = !options.NoShadow; |
||||
|
||||
if (options.CreateXmlOutputFile) { |
||||
helper.XmlOutputFile = Path.Combine(Path.GetDirectoryName(project.OutputAssemblyFullPath), project.AssemblyName + "-TestResult.xml"); |
||||
} |
||||
|
||||
helper.Initialize(project, namespaceFilter, fixture, test); |
||||
helper.Results = Path.GetTempFileName(); |
||||
|
||||
ResetTestResults(project); |
||||
|
||||
testResultsMonitor.FileName = helper.Results; |
||||
testResultsMonitor.Start(); |
||||
|
||||
try { |
||||
RunTests(helper); |
||||
} catch { |
||||
StopMonitoring(); |
||||
throw; |
||||
} |
||||
} else { |
||||
if (IsRunningTest) { |
||||
Stop(); |
||||
} |
||||
if (TaskService.SomethingWentWrong && ErrorListPad.ShowAfterBuild) { |
||||
ShowErrorList(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Clears the test results in the test tree view for the
|
||||
/// project currently being tested.
|
||||
/// </summary>
|
||||
void ResetTestResults(IProject project) |
||||
{ |
||||
TestProject testProject = GetTestProject(project); |
||||
if (testProject != null) { |
||||
testProject.ResetTestResults(); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Clears the test results in the test tree view for all the
|
||||
/// displayed projects.
|
||||
/// </summary>
|
||||
void ResetAllTestResults() |
||||
{ |
||||
if (UnitTestsPad.Instance != null) { |
||||
UnitTestsPad.Instance.ResetTestResults(); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the TestProject associated with the specified project
|
||||
/// from the test tree view.
|
||||
/// </summary>
|
||||
TestProject GetTestProject(IProject project) |
||||
{ |
||||
if (UnitTestsPad.Instance != null) { |
||||
return TestService.TestableProjects.FirstOrDefault(tp => tp.Project == project); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Updates the test result in the test tree view.
|
||||
/// </summary>
|
||||
void UpdateTestResult(TestResult result) |
||||
{ |
||||
TestProject testProject = GetTestProject(currentProject); |
||||
if (testProject != null) { |
||||
testProject.UpdateTestResult(result); |
||||
} |
||||
} |
||||
|
||||
void StopMonitoring() |
||||
{ |
||||
try { |
||||
File.Delete(testResultsMonitor.FileName); |
||||
} catch { } |
||||
|
||||
testResultsMonitor.Dispose(); |
||||
} |
||||
|
||||
void TestFinished(object source, TestFinishedEventArgs e) |
||||
{ |
||||
WorkbenchSingleton.SafeThreadAsyncCall(ShowResult, e.Result); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Custom build command that makes sure errors and warnings
|
||||
/// are not cleared from the Errors list before every build since
|
||||
/// we may be running multiple tests after each other.
|
||||
/// </summary>
|
||||
public class BuildProjectBeforeTestRun : BuildProjectBeforeExecute |
||||
{ |
||||
public BuildProjectBeforeTestRun(IProject targetProject) |
||||
: base(targetProject) |
||||
{ |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Before a build do not clear the tasks, just save any
|
||||
/// dirty files.
|
||||
/// </summary>
|
||||
public override void BeforeBuild() |
||||
{ |
||||
SaveAllFiles.SaveAll(); |
||||
} |
||||
} |
||||
|
||||
public class RunTestInPadCommand : AbstractRunTestCommand |
||||
{ |
||||
ProcessRunner runner; |
||||
|
||||
public RunTestInPadCommand() |
||||
{ |
||||
runner = new ProcessRunner(); |
||||
runner.LogStandardOutputAndError = false; |
||||
runner.OutputLineReceived += OutputLineReceived; |
||||
runner.ProcessExited += ProcessExited; |
||||
} |
||||
|
||||
protected override void RunTests(UnitTestApplicationStartHelper helper) |
||||
{ |
||||
TestRunnerCategory.AppendLine(helper.GetCommandLine()); |
||||
runner.Start(helper.UnitTestApplication, helper.GetArguments()); |
||||
} |
||||
|
||||
protected override void OnStop() |
||||
{ |
||||
runner.Kill(); |
||||
} |
||||
|
||||
protected ProcessRunner GetProcessRunner() |
||||
{ |
||||
return runner; |
||||
} |
||||
|
||||
void OutputLineReceived(object source, LineReceivedEventArgs e) |
||||
{ |
||||
TestRunnerCategory.AppendLine(e.Line); |
||||
} |
||||
|
||||
void ProcessExited(object source, EventArgs e) |
||||
{ |
||||
WorkbenchSingleton.SafeThreadAsyncCall(TestsFinished); |
||||
} |
||||
|
||||
void TestFinished(object source, TestFinishedEventArgs e) |
||||
{ |
||||
WorkbenchSingleton.SafeThreadAsyncCall(ShowResult, e.Result); |
||||
} |
||||
} |
||||
|
||||
public class RunTestWithDebuggerCommand : AbstractRunTestCommand |
||||
{ |
||||
public override void Run() |
||||
{ |
||||
if (DebuggerService.IsDebuggerLoaded && DebuggerService.CurrentDebugger.IsDebugging) { |
||||
if (MessageService.AskQuestion("${res:XML.MainMenu.RunMenu.Compile.StopDebuggingQuestion}", |
||||
"${res:XML.MainMenu.RunMenu.Compile.StopDebuggingTitle}")) |
||||
{ |
||||
DebuggerService.CurrentDebugger.Stop(); |
||||
base.Run(); |
||||
} |
||||
} else { |
||||
base.Run(); |
||||
} |
||||
} |
||||
|
||||
protected override void RunTests(UnitTestApplicationStartHelper helper) |
||||
{ |
||||
bool running = false; |
||||
|
||||
try { |
||||
TestRunnerCategory.AppendLine(helper.GetCommandLine()); |
||||
ProcessStartInfo startInfo = new ProcessStartInfo(helper.UnitTestApplication); |
||||
startInfo.Arguments = helper.GetArguments(); |
||||
startInfo.WorkingDirectory = UnitTestApplicationStartHelper.UnitTestApplicationDirectory; |
||||
DebuggerService.DebugStopped += DebuggerFinished; |
||||
DebuggerService.CurrentDebugger.Start(startInfo); |
||||
running = true; |
||||
} finally { |
||||
if (!running) { |
||||
DebuggerService.DebugStopped -= DebuggerFinished; |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected override void OnStop() |
||||
{ |
||||
if (DebuggerService.CurrentDebugger.IsDebugging) { |
||||
DebuggerService.CurrentDebugger.Stop(); |
||||
} |
||||
} |
||||
|
||||
void DebuggerFinished(object sender, EventArgs e) |
||||
{ |
||||
DebuggerService.DebugStopped -= DebuggerFinished; |
||||
WorkbenchSingleton.SafeThreadAsyncCall(TestsFinished); |
||||
} |
||||
} |
||||
|
||||
public class RunAllTestsInPadCommand : RunTestInPadCommand |
||||
{ |
||||
public override void Run() |
||||
{ |
||||
// To make sure all tests are run we set the Owner to null.
|
||||
Owner = null; |
||||
base.Run(); |
||||
} |
||||
} |
||||
|
||||
public class RunProjectTestsInPadCommand : RunTestInPadCommand, ITestTreeView |
||||
{ |
||||
public override void Run() |
||||
{ |
||||
Owner = this; |
||||
base.Run(); |
||||
} |
||||
|
||||
public TestMember SelectedMethod { |
||||
get { return null; } |
||||
} |
||||
|
||||
public TestClass SelectedClass { |
||||
get { return null; } |
||||
} |
||||
|
||||
public IProject SelectedProject { |
||||
get { return ProjectService.CurrentProject; } |
||||
} |
||||
|
||||
public string SelectedNamespace { |
||||
get { return null; } |
||||
} |
||||
} |
||||
} |
||||
@ -1,72 +0,0 @@
@@ -1,72 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Collections.Specialized; |
||||
using System.Linq; |
||||
using System.Reflection; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Media; |
||||
using System.Windows.Media.Imaging; |
||||
|
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.NRefactory.TypeSystem.Implementation; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Parser; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using ICSharpCode.TreeView; |
||||
using NUnit.Framework; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public static class Extensions |
||||
{ |
||||
public static IEnumerable<TResult> FullOuterJoin<TOuter, TInner, TKey, TResult>(this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter,TKey> outerKeySelector, Func<TInner,TKey> innerKeySelector, Func<TOuter,TInner,TResult> resultSelector) |
||||
where TInner : class |
||||
where TOuter : class |
||||
{ |
||||
var innerLookup = inner.ToLookup(innerKeySelector); |
||||
var outerLookup = outer.ToLookup(outerKeySelector); |
||||
|
||||
var innerJoinItems = inner |
||||
.Where(innerItem => !outerLookup.Contains(innerKeySelector(innerItem))) |
||||
.Select(innerItem => resultSelector(null, innerItem)); |
||||
|
||||
return outer |
||||
.SelectMany(outerItem => { |
||||
var innerItems = innerLookup[outerKeySelector(outerItem)]; |
||||
|
||||
return innerItems.Any() ? innerItems : new TInner[] { null }; |
||||
}, resultSelector) |
||||
.Concat(innerJoinItems); |
||||
} |
||||
|
||||
public static void OrderedInsert<T>(this IList<T> list, T item, Func<T, T, int> comparer) |
||||
{ |
||||
int index = 0; |
||||
while (index < list.Count && comparer(list[index], item) < 0) |
||||
index++; |
||||
list.Insert(index, item); |
||||
} |
||||
|
||||
public static void UpdateTestClasses(this IList<TestClass> testClasses, IRegisteredTestFrameworks testFrameworks, IReadOnlyList<ITypeDefinition> oldTypes, IReadOnlyList<ITypeDefinition> newTypes, TestClass parent, TestProject project) |
||||
{ |
||||
var mappings = oldTypes.FullOuterJoin(newTypes, t => t.ReflectionName, t => t.ReflectionName, Tuple.Create); |
||||
foreach (Tuple<ITypeDefinition, ITypeDefinition> mapping in mappings) { |
||||
if (mapping.Item2 == null) |
||||
testClasses.RemoveWhere(c => c.FullName == mapping.Item1.ReflectionName); |
||||
else if (mapping.Item1 == null) |
||||
testClasses.Add(new TestClass(project, testFrameworks, mapping.Item2.ReflectionName, mapping.Item2, parent)); |
||||
else { |
||||
var testClass = testClasses.SingleOrDefault(c => c.FullName == mapping.Item1.ReflectionName); |
||||
if (testClass == null) |
||||
testClasses.Add(new TestClass(project, testFrameworks, mapping.Item2.ReflectionName, mapping.Item2, parent)); |
||||
else |
||||
testClass.UpdateClass(mapping.Item2); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,13 +0,0 @@
@@ -1,13 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public interface IUnitTestFileService : IFileSystem |
||||
{ |
||||
void OpenFile(string fileName); |
||||
void JumpToFilePosition(string fileName, int line, int column); |
||||
} |
||||
} |
||||
@ -0,0 +1,157 @@
@@ -0,0 +1,157 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Collections.ObjectModel; |
||||
using System.Linq; |
||||
|
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Parser; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
/// <summary>
|
||||
/// Manages the collection of TestProjects.
|
||||
/// </summary>
|
||||
public class TestSolution |
||||
{ |
||||
readonly IRegisteredTestFrameworks registeredTestFrameworks; |
||||
readonly List<ProjectChangeListener> changeListeners = new List<ProjectChangeListener>(); |
||||
readonly ObservableCollection<TestProject> testableProjects = new ObservableCollection<TestProject>(); |
||||
|
||||
public ObservableCollection<TestProject> TestableProjects { |
||||
get { return testableProjects; } |
||||
} |
||||
|
||||
public TestSolution(IRegisteredTestFrameworks registeredTestFrameworks) |
||||
{ |
||||
if (registeredTestFrameworks == null) |
||||
throw new ArgumentNullException("registeredTestFrameworks"); |
||||
this.registeredTestFrameworks = registeredTestFrameworks; |
||||
ProjectService.SolutionLoaded += ProjectService_SolutionLoaded; |
||||
ProjectService.SolutionClosed += ProjectService_SolutionClosed; |
||||
ProjectService.ProjectAdded += ProjectService_ProjectAdded; |
||||
ProjectService.ProjectRemoved += ProjectService_ProjectRemoved; |
||||
SD.ParserService.LoadSolutionProjectsThread.Finished += SD_ParserService_LoadSolutionProjectsThread_Finished; |
||||
if (ProjectService.OpenSolution != null) { |
||||
ProjectService_SolutionLoaded(null, new SolutionEventArgs(ProjectService.OpenSolution)); |
||||
SD_ParserService_LoadSolutionProjectsThread_Finished(null, null); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Retrieves the TestProject for the specified project.
|
||||
/// </summary>
|
||||
public TestProject GetTestProject(IProject currentProject) |
||||
{ |
||||
return testableProjects.FirstOrDefault(p => p.Project == currentProject); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Creates a TestProject for an IProject.
|
||||
/// This class takes care of changes in the test framework and will recreate the testProject
|
||||
/// if the test framework changes.
|
||||
/// </summary>
|
||||
class ProjectChangeListener |
||||
{ |
||||
readonly TestSolution testSolution; |
||||
internal readonly IProject project; |
||||
TestProject testProject; |
||||
|
||||
public ProjectChangeListener(TestSolution testSolution, IProject project) |
||||
{ |
||||
this.testSolution = testSolution; |
||||
this.project = project; |
||||
} |
||||
|
||||
public void Start() |
||||
{ |
||||
project.ParseInformationUpdated += project_ParseInformationUpdated; |
||||
CheckTestFramework(); |
||||
} |
||||
|
||||
public void Stop() |
||||
{ |
||||
project.ParseInformationUpdated -= project_ParseInformationUpdated; |
||||
// Remove old testProject
|
||||
if (testProject != null) { |
||||
testSolution.testableProjects.Remove(testProject); |
||||
testProject = null; |
||||
} |
||||
} |
||||
|
||||
void project_ParseInformationUpdated(object sender, ParseInformationEventArgs e) |
||||
{ |
||||
if (testProject != null) { |
||||
testProject.NotifyParseInformationChanged(e.OldUnresolvedFile, e.NewUnresolvedFile); |
||||
} |
||||
} |
||||
|
||||
internal void CheckTestFramework() |
||||
{ |
||||
ITestFramework newTestFramework = testSolution.registeredTestFrameworks.GetTestFrameworkForProject(project); |
||||
if (newTestFramework != null && testProject != null && testProject.TestFramework == newTestFramework) |
||||
return; // test framework is unchanged
|
||||
|
||||
// Remove old testProject
|
||||
if (testProject != null) { |
||||
testSolution.testableProjects.Remove(testProject); |
||||
testProject = null; |
||||
} |
||||
// Create new testProject
|
||||
if (newTestFramework != null) { |
||||
testProject = new TestProject(project, newTestFramework); |
||||
testSolution.testableProjects.Add(testProject); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void ProjectService_ProjectAdded(object sender, ProjectEventArgs e) |
||||
{ |
||||
AddProject(e.Project); |
||||
} |
||||
|
||||
void AddProject(IProject project) |
||||
{ |
||||
ProjectChangeListener listener = new ProjectChangeListener(this, project); |
||||
changeListeners.Add(listener); |
||||
listener.Start(); |
||||
} |
||||
|
||||
void ProjectService_ProjectRemoved(object sender, ProjectEventArgs e) |
||||
{ |
||||
for (int i = 0; i < changeListeners.Count; i++) { |
||||
if (changeListeners[i].project == e.Project) { |
||||
changeListeners[i].Stop(); |
||||
changeListeners.RemoveAt(i); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
void ProjectService_SolutionClosed(object sender, EventArgs e) |
||||
{ |
||||
for (int i = 0; i < changeListeners.Count; i++) { |
||||
changeListeners[i].Stop(); |
||||
} |
||||
changeListeners.Clear(); |
||||
} |
||||
|
||||
void ProjectService_SolutionLoaded(object sender, SolutionEventArgs e) |
||||
{ |
||||
ProjectService_SolutionClosed(sender, e); |
||||
foreach (var project in e.Solution.Projects) { |
||||
AddProject(project); |
||||
} |
||||
} |
||||
|
||||
void SD_ParserService_LoadSolutionProjectsThread_Finished(object sender, EventArgs e) |
||||
{ |
||||
for (int i = 0; i < changeListeners.Count; i++) { |
||||
changeListeners[i].CheckTestFramework(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,102 +0,0 @@
@@ -1,102 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.Core; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
/// <summary>
|
||||
/// All Tests root tree node that is added to the test tree when the
|
||||
/// solution has multiple test projects.
|
||||
/// </summary>
|
||||
public class AllTestsTreeNode : TestTreeNode |
||||
{ |
||||
public AllTestsTreeNode() |
||||
: base(null, StringParser.Parse("${res:ICSharpCode.UnitTesting.AllTestsTreeNode.Text}")) |
||||
{ |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Raised when the all tests tree node is disposed.
|
||||
/// </summary>
|
||||
public event EventHandler Disposed; |
||||
|
||||
/// <summary>
|
||||
/// Disposes this tree node.
|
||||
/// </summary>
|
||||
public override void Dispose() |
||||
{ |
||||
base.Dispose(); |
||||
if (Disposed != null) { |
||||
Disposed(this, new EventArgs()); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Adds a new project node as a child of the All Tests node.
|
||||
/// </summary>
|
||||
public void AddProjectNode(TestProjectTreeNode node) |
||||
{ |
||||
node.AddTo(this); |
||||
node.ImageIndexChanged += TestProjectTreeNodeImageIndexChanged; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Removes the project node.
|
||||
/// </summary>
|
||||
public void RemoveProjectNode(TestProjectTreeNode node) |
||||
{ |
||||
if (Nodes.Contains(node)) { |
||||
node.ImageIndexChanged -= TestProjectTreeNodeImageIndexChanged; |
||||
node.Remove(); |
||||
} |
||||
} |
||||
|
||||
void TestProjectTreeNodeImageIndexChanged(object source, EventArgs e) |
||||
{ |
||||
UpdateImageListIndex(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Sets the All Tests image index based on the current image
|
||||
/// indexes of the child project tree nodes.
|
||||
/// </summary>
|
||||
void UpdateImageListIndex() |
||||
{ |
||||
int ignored = 0; |
||||
int failed = 0; |
||||
int passed = 0; |
||||
int notRun = 0; |
||||
int total = Nodes.Count; |
||||
|
||||
foreach (TestProjectTreeNode projectNode in Nodes) { |
||||
switch (projectNode.ImageIndex) { |
||||
case (int)TestTreeViewImageListIndex.TestFailed: |
||||
failed++; |
||||
break; |
||||
case (int)TestTreeViewImageListIndex.TestPassed: |
||||
passed++; |
||||
break; |
||||
case (int)TestTreeViewImageListIndex.TestIgnored: |
||||
ignored++; |
||||
break; |
||||
default: // Not run.
|
||||
notRun++; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
// Update the image index based on the test project results.
|
||||
if (failed > 0) { |
||||
UpdateImageListIndex(TestResultType.Failure); |
||||
} else if (ignored > 0) { |
||||
UpdateImageListIndex(TestResultType.Ignored); |
||||
} else if (passed > 0 && notRun == 0) { |
||||
UpdateImageListIndex(TestResultType.Success); |
||||
} else { |
||||
UpdateImageListIndex(TestResultType.None); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,53 +0,0 @@
@@ -1,53 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Linq; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class EmptyUnitTestsPad : IUnitTestsPad |
||||
{ |
||||
Solution solution; |
||||
|
||||
public EmptyUnitTestsPad() |
||||
: this(null) |
||||
{ |
||||
} |
||||
|
||||
public EmptyUnitTestsPad(Solution solution) |
||||
{ |
||||
this.solution = solution; |
||||
} |
||||
|
||||
public void UpdateToolbar() |
||||
{ |
||||
} |
||||
|
||||
public void BringToFront() |
||||
{ |
||||
} |
||||
|
||||
public void ResetTestResults() |
||||
{ |
||||
} |
||||
|
||||
public IProject[] GetProjects() |
||||
{ |
||||
if (solution != null) { |
||||
return solution.Projects.ToArray(); |
||||
} |
||||
return new IProject[0]; |
||||
} |
||||
|
||||
public TestProject GetTestProject(IProject project) |
||||
{ |
||||
return null; |
||||
} |
||||
|
||||
public void CollapseAll() |
||||
{ |
||||
} |
||||
} |
||||
} |
||||
@ -1,23 +0,0 @@
@@ -1,23 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public delegate void MessageReceivedEventHandler(object sender, MessageReceivedEventArgs e); |
||||
|
||||
public class MessageReceivedEventArgs : EventArgs |
||||
{ |
||||
string message; |
||||
|
||||
public MessageReceivedEventArgs(string message) |
||||
{ |
||||
this.message = message; |
||||
} |
||||
|
||||
public string Message { |
||||
get { return message; } |
||||
} |
||||
} |
||||
} |
||||
@ -1,47 +0,0 @@
@@ -1,47 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
/// <summary>
|
||||
/// IBuildable implementation that builds several projects.
|
||||
/// </summary>
|
||||
public class MultipleProjectBuildable : IBuildable |
||||
{ |
||||
readonly IBuildable[] projects; |
||||
|
||||
public MultipleProjectBuildable(IEnumerable<IBuildable> projects) |
||||
{ |
||||
this.projects = projects.ToArray(); |
||||
} |
||||
|
||||
public string Name { |
||||
get { return string.Empty; } |
||||
} |
||||
|
||||
public Solution ParentSolution { |
||||
get { return projects.Length > 0 ? projects[0].ParentSolution : null; } |
||||
} |
||||
|
||||
public ICollection<IBuildable> GetBuildDependencies(ProjectBuildOptions buildOptions) |
||||
{ |
||||
return projects; |
||||
} |
||||
|
||||
public void StartBuild(ProjectBuildOptions buildOptions, IBuildFeedbackSink feedbackSink) |
||||
{ |
||||
// SharpDevelop already has built our dependencies, so we're done immediately.
|
||||
feedbackSink.Done(true); |
||||
} |
||||
|
||||
public ProjectBuildOptions CreateProjectBuildOptions(BuildOptions options, bool isRootBuildable) |
||||
{ |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
@ -1,26 +0,0 @@
@@ -1,26 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class RunAllTestsInPadCommand : RunTestInPadCommand |
||||
{ |
||||
public RunAllTestsInPadCommand() |
||||
{ |
||||
} |
||||
|
||||
public RunAllTestsInPadCommand(IRunTestCommandContext context) |
||||
: base(context) |
||||
{ |
||||
} |
||||
|
||||
public override void Run() |
||||
{ |
||||
// To make sure all tests are run we set the Owner to null.
|
||||
Owner = null; |
||||
base.Run(); |
||||
} |
||||
} |
||||
} |
||||
@ -1,546 +0,0 @@
@@ -1,546 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Diagnostics; |
||||
using System.IO; |
||||
|
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Commands; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using ICSharpCode.SharpDevelop.Project.Commands; |
||||
using ICSharpCode.SharpDevelop.Util; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public abstract class AbstractRunTestCommand : AbstractMenuCommand |
||||
{ |
||||
static MessageViewCategory testRunnerCategory; |
||||
static AbstractRunTestCommand runningTestCommand; |
||||
List<IProject> projects; |
||||
IProject currentProject; |
||||
TestResultsMonitor testResultsMonitor; |
||||
|
||||
public AbstractRunTestCommand() |
||||
{ |
||||
testResultsMonitor = new TestResultsMonitor(); |
||||
testResultsMonitor.TestFinished += TestFinished; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the running test command.
|
||||
/// </summary>
|
||||
public static AbstractRunTestCommand RunningTestCommand { |
||||
get { |
||||
return runningTestCommand; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets whether a test is currently running.
|
||||
/// </summary>
|
||||
public static bool IsRunningTest { |
||||
get { |
||||
return runningTestCommand != null; |
||||
} |
||||
} |
||||
|
||||
public override void Run() |
||||
{ |
||||
projects = new List<IProject>(); |
||||
|
||||
IMember m = TestableCondition.GetMember(Owner); |
||||
IClass c = (m != null) ? m.DeclaringType : TestableCondition.GetClass(Owner); |
||||
IProject project = TestableCondition.GetProject(Owner); |
||||
string namespaceFilter = TestableCondition.GetNamespace(Owner); |
||||
|
||||
if (project != null) { |
||||
projects.Add(project); |
||||
} else if (UnitTestsPad.Instance != null) { |
||||
projects.AddRange(UnitTestsPad.Instance.TestTreeView.GetProjects()); |
||||
} |
||||
|
||||
if (projects.Count > 0) { |
||||
runningTestCommand = this; |
||||
try { |
||||
BeforeRun(); |
||||
if (IsRunningTest) { |
||||
currentProject = projects[0]; |
||||
Run(currentProject, namespaceFilter, c, m); |
||||
} |
||||
} catch { |
||||
runningTestCommand = null; |
||||
throw; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public static MessageViewCategory TestRunnerCategory { |
||||
get { |
||||
if (testRunnerCategory == null) { |
||||
MessageViewCategory.Create(ref testRunnerCategory, "UnitTesting", "${res:ICSharpCode.NUnitPad.NUnitPadContent.PadName}"); |
||||
} |
||||
return testRunnerCategory; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Stops running the tests.
|
||||
/// </summary>
|
||||
public void Stop() |
||||
{ |
||||
runningTestCommand = null; |
||||
UpdateUnitTestsPadToolbar(); |
||||
|
||||
projects.Clear(); |
||||
|
||||
testResultsMonitor.Stop(); |
||||
StopMonitoring(); |
||||
|
||||
OnStop(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Called before all tests are run. If multiple projects are
|
||||
/// to be tested this is called only once.
|
||||
/// </summary>
|
||||
protected virtual void OnBeforeRunTests() |
||||
{ |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Called after all tests have been run even if there have
|
||||
/// been errors. If multiple projects are to be tested this is called only once.
|
||||
/// </summary>
|
||||
protected virtual void OnAfterRunTests() |
||||
{ |
||||
} |
||||
|
||||
protected abstract void RunTests(UnitTestApplicationStartHelper helper); |
||||
|
||||
/// <summary>
|
||||
/// Called by derived classes when a single test run
|
||||
/// is finished.
|
||||
/// </summary>
|
||||
protected void TestsFinished() |
||||
{ |
||||
WorkbenchSingleton.AssertMainThread(); |
||||
|
||||
// Read the rest of the file just in case.
|
||||
testResultsMonitor.Stop(); |
||||
testResultsMonitor.Read(); |
||||
StopMonitoring(); |
||||
|
||||
projects.Remove(currentProject); |
||||
if (projects.Count > 0) { |
||||
currentProject = projects[0]; |
||||
Run(currentProject, null, null, null); |
||||
} else { |
||||
runningTestCommand = null; |
||||
UpdateUnitTestsPadToolbar(); |
||||
if (TaskService.SomethingWentWrong && ErrorListPad.ShowAfterBuild) { |
||||
ShowErrorList(); |
||||
} |
||||
OnAfterRunTests(); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Called by derived classes to show a single test result.
|
||||
/// </summary>
|
||||
protected void ShowResult(TestResult result) |
||||
{ |
||||
if (result.IsFailure || result.IsIgnored) { |
||||
TaskService.Add(CreateTask(result)); |
||||
} |
||||
UpdateTestResult(result); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Called when the test run should be stopped.
|
||||
/// </summary>
|
||||
protected virtual void OnStop() |
||||
{ |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Brings the specified pad to the front.
|
||||
/// </summary>
|
||||
protected void ShowPad(PadDescriptor padDescriptor) |
||||
{ |
||||
if (padDescriptor != null) { |
||||
WorkbenchSingleton.SafeThreadAsyncCall(padDescriptor.BringPadToFront); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Runs the tests after building the project under test.
|
||||
/// </summary>
|
||||
void Run(IProject project, string namespaceFilter, IClass fixture, IMember test) |
||||
{ |
||||
BuildProjectBeforeTestRun build = new BuildProjectBeforeTestRun(project); |
||||
build.BuildComplete += delegate { |
||||
OnBuildComplete(build.LastBuildResults, project, namespaceFilter, fixture, test); |
||||
}; |
||||
build.Run(); |
||||
} |
||||
|
||||
void ShowUnitTestsPad() |
||||
{ |
||||
ShowPad(WorkbenchSingleton.Workbench.GetPad(typeof(UnitTestsPad))); |
||||
} |
||||
|
||||
void UpdateUnitTestsPadToolbar() |
||||
{ |
||||
if (UnitTestsPad.Instance != null) { |
||||
UnitTestsPad.Instance.UpdateToolbar(); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Sets the initial workbench state before starting
|
||||
/// a test run.
|
||||
/// </summary>
|
||||
void BeforeRun() |
||||
{ |
||||
TaskService.BuildMessageViewCategory.ClearText(); |
||||
TaskService.InUpdate = true; |
||||
TaskService.ClearExceptCommentTasks(); |
||||
TaskService.InUpdate = false; |
||||
|
||||
TestRunnerCategory.ClearText(); |
||||
|
||||
ShowUnitTestsPad(); |
||||
ShowOutputPad(); |
||||
|
||||
UpdateUnitTestsPadToolbar(); |
||||
ResetAllTestResults(); |
||||
|
||||
OnBeforeRunTests(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Brings output pad to the front.
|
||||
/// </summary>
|
||||
void ShowOutputPad() |
||||
{ |
||||
ShowPad(WorkbenchSingleton.Workbench.GetPad(typeof(CompilerMessageView))); |
||||
} |
||||
|
||||
Task CreateTask(TestResult result) |
||||
{ |
||||
TaskType taskType = TaskType.Warning; |
||||
FileLineReference lineRef = null; |
||||
string message = String.Empty; |
||||
|
||||
if (result.IsFailure) { |
||||
taskType = TaskType.Error; |
||||
lineRef = OutputTextLineParser.GetNUnitOutputFileLineReference(result.StackTrace, true); |
||||
message = GetTestResultMessage(result, "${res:NUnitPad.NUnitPadContent.TestTreeView.TestFailedMessage}"); |
||||
} else if (result.IsIgnored) { |
||||
message = GetTestResultMessage(result, "${res:NUnitPad.NUnitPadContent.TestTreeView.TestNotExecutedMessage}"); |
||||
} |
||||
if (lineRef == null) { |
||||
lineRef = FindTest(result.Name); |
||||
} |
||||
if (lineRef != null) { |
||||
return new Task(FileName.Create(lineRef.FileName), |
||||
message, lineRef.Column, lineRef.Line, taskType); |
||||
} |
||||
return new Task(null, message, 0, 0, taskType); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Returns the test result message if there is on otherwise
|
||||
/// uses the string resource to create a message.
|
||||
/// </summary>
|
||||
string GetTestResultMessage(TestResult result, string stringResource) |
||||
{ |
||||
if (result.Message.Length > 0) { |
||||
return result.Message; |
||||
} |
||||
return StringParser.Parse(stringResource, new string[,] {{"TestCase", result.Name}}); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Returns the location of the specified test method in the
|
||||
/// project being tested.
|
||||
/// </summary>
|
||||
FileLineReference FindTest(string methodName) |
||||
{ |
||||
TestProject testProject = GetTestProject(currentProject); |
||||
if (testProject != null) { |
||||
TestMethod method = testProject.TestClasses.GetTestMethod(methodName); |
||||
if (method != null) { |
||||
MemberResolveResult resolveResult = new MemberResolveResult(null, null, method.Method); |
||||
FilePosition filePos = resolveResult.GetDefinitionPosition(); |
||||
return new FileLineReference(filePos.FileName, filePos.Line, filePos.Column); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
void ShowErrorList() |
||||
{ |
||||
ShowPad(WorkbenchSingleton.Workbench.GetPad(typeof(ErrorListPad))); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Runs the test for the project after a successful build.
|
||||
/// </summary>
|
||||
void OnBuildComplete(BuildResults results, IProject project, string namespaceFilter, IClass fixture, IMember test) |
||||
{ |
||||
if (results.ErrorCount == 0 && IsRunningTest) { |
||||
UnitTestApplicationStartHelper helper = new UnitTestApplicationStartHelper(); |
||||
|
||||
UnitTestingOptions options = new UnitTestingOptions(); |
||||
helper.NoThread = options.NoThread; |
||||
helper.NoLogo = options.NoLogo; |
||||
helper.NoDots = options.NoDots; |
||||
helper.Labels = options.Labels; |
||||
helper.ShadowCopy = !options.NoShadow; |
||||
|
||||
if (options.CreateXmlOutputFile) { |
||||
helper.XmlOutputFile = Path.Combine(Path.GetDirectoryName(project.OutputAssemblyFullPath), project.AssemblyName + "-TestResult.xml"); |
||||
} |
||||
|
||||
helper.Initialize(project, namespaceFilter, fixture, test); |
||||
helper.Results = Path.GetTempFileName(); |
||||
|
||||
ResetTestResults(project); |
||||
|
||||
testResultsMonitor.FileName = helper.Results; |
||||
testResultsMonitor.Start(); |
||||
|
||||
try { |
||||
RunTests(helper); |
||||
} catch { |
||||
StopMonitoring(); |
||||
throw; |
||||
} |
||||
} else { |
||||
if (IsRunningTest) { |
||||
Stop(); |
||||
} |
||||
if (TaskService.SomethingWentWrong && ErrorListPad.ShowAfterBuild) { |
||||
ShowErrorList(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Clears the test results in the test tree view for the
|
||||
/// project currently being tested.
|
||||
/// </summary>
|
||||
void ResetTestResults(IProject project) |
||||
{ |
||||
TestProject testProject = GetTestProject(project); |
||||
if (testProject != null) { |
||||
testProject.ResetTestResults(); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Clears the test results in the test tree view for all the
|
||||
/// displayed projects.
|
||||
/// </summary>
|
||||
void ResetAllTestResults() |
||||
{ |
||||
if (UnitTestsPad.Instance != null) { |
||||
UnitTestsPad.Instance.TestTreeView.ResetTestResults(); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the TestProject associated with the specified project
|
||||
/// from the test tree view.
|
||||
/// </summary>
|
||||
TestProject GetTestProject(IProject project) |
||||
{ |
||||
if (UnitTestsPad.Instance != null) { |
||||
return UnitTestsPad.Instance.TestTreeView.GetTestProject(project); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Updates the test result in the test tree view.
|
||||
/// </summary>
|
||||
void UpdateTestResult(TestResult result) |
||||
{ |
||||
TestProject testProject = GetTestProject(currentProject); |
||||
if (testProject != null) { |
||||
testProject.UpdateTestResult(result); |
||||
} |
||||
} |
||||
|
||||
void StopMonitoring() |
||||
{ |
||||
try { |
||||
File.Delete(testResultsMonitor.FileName); |
||||
} catch { } |
||||
|
||||
testResultsMonitor.Dispose(); |
||||
} |
||||
|
||||
void TestFinished(object source, TestFinishedEventArgs e) |
||||
{ |
||||
WorkbenchSingleton.SafeThreadAsyncCall(ShowResult, e.Result); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Custom build command that makes sure errors and warnings
|
||||
/// are not cleared from the Errors list before every build since
|
||||
/// we may be running multiple tests after each other.
|
||||
/// </summary>
|
||||
public class BuildProjectBeforeTestRun : BuildProjectBeforeExecute |
||||
{ |
||||
public BuildProjectBeforeTestRun(IProject targetProject) |
||||
: base(targetProject) |
||||
{ |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Before a build do not clear the tasks, just save any
|
||||
/// dirty files.
|
||||
/// </summary>
|
||||
public override void BeforeBuild() |
||||
{ |
||||
SaveAllFiles.SaveAll(); |
||||
} |
||||
} |
||||
|
||||
public class RunTestInPadCommand : AbstractRunTestCommand |
||||
{ |
||||
ProcessRunner runner; |
||||
|
||||
public RunTestInPadCommand() |
||||
{ |
||||
runner = new ProcessRunner(); |
||||
runner.LogStandardOutputAndError = false; |
||||
runner.OutputLineReceived += OutputLineReceived; |
||||
runner.ProcessExited += ProcessExited; |
||||
} |
||||
|
||||
protected override void RunTests(UnitTestApplicationStartHelper helper) |
||||
{ |
||||
TestRunnerCategory.AppendLine(helper.GetCommandLine()); |
||||
runner.Start(helper.UnitTestApplication, helper.GetArguments()); |
||||
} |
||||
|
||||
protected override void OnStop() |
||||
{ |
||||
runner.Kill(); |
||||
} |
||||
|
||||
protected ProcessRunner GetProcessRunner() |
||||
{ |
||||
return runner; |
||||
} |
||||
|
||||
void OutputLineReceived(object source, LineReceivedEventArgs e) |
||||
{ |
||||
TestRunnerCategory.AppendLine(e.Line); |
||||
} |
||||
|
||||
void ProcessExited(object source, EventArgs e) |
||||
{ |
||||
WorkbenchSingleton.SafeThreadAsyncCall(TestsFinished); |
||||
} |
||||
|
||||
void TestFinished(object source, TestFinishedEventArgs e) |
||||
{ |
||||
WorkbenchSingleton.SafeThreadAsyncCall(ShowResult, e.Result); |
||||
} |
||||
} |
||||
|
||||
public class RunTestWithDebuggerCommand : AbstractRunTestCommand |
||||
{ |
||||
public override void Run() |
||||
{ |
||||
if (DebuggerService.IsDebuggerLoaded && DebuggerService.CurrentDebugger.IsDebugging) { |
||||
if (MessageService.AskQuestion("${res:XML.MainMenu.RunMenu.Compile.StopDebuggingQuestion}", |
||||
"${res:XML.MainMenu.RunMenu.Compile.StopDebuggingTitle}")) |
||||
{ |
||||
DebuggerService.CurrentDebugger.Stop(); |
||||
base.Run(); |
||||
} |
||||
} else { |
||||
base.Run(); |
||||
} |
||||
} |
||||
|
||||
protected override void RunTests(UnitTestApplicationStartHelper helper) |
||||
{ |
||||
bool running = false; |
||||
|
||||
try { |
||||
TestRunnerCategory.AppendLine(helper.GetCommandLine()); |
||||
ProcessStartInfo startInfo = new ProcessStartInfo(helper.UnitTestApplication); |
||||
startInfo.Arguments = helper.GetArguments(); |
||||
startInfo.WorkingDirectory = UnitTestApplicationStartHelper.UnitTestApplicationDirectory; |
||||
DebuggerService.DebugStopped += DebuggerFinished; |
||||
DebuggerService.CurrentDebugger.Start(startInfo); |
||||
running = true; |
||||
} finally { |
||||
if (!running) { |
||||
DebuggerService.DebugStopped -= DebuggerFinished; |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected override void OnStop() |
||||
{ |
||||
if (DebuggerService.CurrentDebugger.IsDebugging) { |
||||
DebuggerService.CurrentDebugger.Stop(); |
||||
} |
||||
} |
||||
|
||||
void DebuggerFinished(object sender, EventArgs e) |
||||
{ |
||||
DebuggerService.DebugStopped -= DebuggerFinished; |
||||
WorkbenchSingleton.SafeThreadAsyncCall(TestsFinished); |
||||
} |
||||
} |
||||
|
||||
public class RunAllTestsInPadCommand : RunTestInPadCommand |
||||
{ |
||||
public override void Run() |
||||
{ |
||||
// To make sure all tests are run we set the Owner to null.
|
||||
Owner = null; |
||||
base.Run(); |
||||
} |
||||
} |
||||
|
||||
public class RunProjectTestsInPadCommand : RunTestInPadCommand, ITestTreeView |
||||
{ |
||||
public override void Run() |
||||
{ |
||||
Owner = this; |
||||
base.Run(); |
||||
} |
||||
|
||||
public IMember SelectedMethod { |
||||
get { return null; } |
||||
} |
||||
|
||||
public IClass SelectedClass { |
||||
get { return null; } |
||||
} |
||||
|
||||
public IProject SelectedProject { |
||||
get { return ProjectService.CurrentProject; } |
||||
} |
||||
|
||||
public string SelectedNamespace { |
||||
get { return null; } |
||||
} |
||||
} |
||||
} |
||||
@ -1,26 +0,0 @@
@@ -1,26 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using ICSharpCode.SharpDevelop.Util; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class RunTestInPadCommand : AbstractRunTestCommand |
||||
{ |
||||
public RunTestInPadCommand() |
||||
{ |
||||
} |
||||
|
||||
public RunTestInPadCommand(IRunTestCommandContext context) |
||||
: base(context) |
||||
{ |
||||
} |
||||
|
||||
protected override ITestRunner CreateTestRunner(IProject project) |
||||
{ |
||||
return Context.RegisteredTestFrameworks.CreateTestRunner(project); |
||||
} |
||||
} |
||||
} |
||||
@ -1,26 +0,0 @@
@@ -1,26 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class RunTestWithDebuggerCommand : AbstractRunTestCommand |
||||
{ |
||||
public RunTestWithDebuggerCommand() |
||||
{ |
||||
} |
||||
|
||||
public RunTestWithDebuggerCommand(IRunTestCommandContext context) |
||||
: base(context) |
||||
{ |
||||
} |
||||
|
||||
protected override ITestRunner CreateTestRunner(IProject project) |
||||
{ |
||||
return Context.RegisteredTestFrameworks.CreateTestDebugger(project); |
||||
} |
||||
} |
||||
} |
||||
@ -1,19 +0,0 @@
@@ -1,19 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.Core; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
/// <summary>
|
||||
/// Determines whether #develop is currently running unit tests.
|
||||
/// </summary>
|
||||
public class RunningTestsCondition : IConditionEvaluator |
||||
{ |
||||
public bool IsValid(object caller, Condition condition) |
||||
{ |
||||
return AbstractRunTestCommand.IsRunningTest; |
||||
} |
||||
} |
||||
} |
||||
@ -1,214 +0,0 @@
@@ -1,214 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Collections.ObjectModel; |
||||
using ICSharpCode.Core; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class TestClassCollection : KeyedCollection<string, TestClass> |
||||
{ |
||||
TestResultType testResult = TestResultType.None; |
||||
|
||||
Dictionary<string, TestClass> passedTestClasses = new Dictionary<string, TestClass>(); |
||||
Dictionary<string, TestClass> failedTestClasses = new Dictionary<string, TestClass>(); |
||||
Dictionary<string, TestClass> ignoredTestClasses = new Dictionary<string, TestClass>(); |
||||
|
||||
/// <summary>
|
||||
/// Raised when the test result for this collection of
|
||||
/// classes has changed.
|
||||
/// </summary>
|
||||
public event EventHandler ResultChanged; |
||||
|
||||
/// <summary>
|
||||
/// Raised when a class is added to this collection.
|
||||
/// </summary>
|
||||
public event TestClassEventHandler TestClassAdded; |
||||
|
||||
/// <summary>
|
||||
/// Raised when a class is removed from this collection.
|
||||
/// </summary>
|
||||
public event TestClassEventHandler TestClassRemoved; |
||||
|
||||
/// <summary>
|
||||
/// Gets the overall test results for the collection of
|
||||
/// test classes.
|
||||
/// </summary>
|
||||
public TestResultType Result { |
||||
get { |
||||
return testResult; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Sets all the test class test results back to none.
|
||||
/// </summary>
|
||||
public void ResetTestResults() |
||||
{ |
||||
passedTestClasses.Clear(); |
||||
failedTestClasses.Clear(); |
||||
ignoredTestClasses.Clear(); |
||||
|
||||
foreach (TestClass c in this) { |
||||
c.ResetTestResults(); |
||||
} |
||||
|
||||
SetTestResult(TestResultType.None); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Updates the test method with the specified test result.
|
||||
/// </summary>
|
||||
public void UpdateTestResult(TestResult testResult) |
||||
{ |
||||
TestClass testClass = GetTestClassFromTestMemberName(testResult.Name); |
||||
if (testClass != null) { |
||||
testClass.UpdateTestResult(testResult); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the matching test member from this set of classes.
|
||||
/// </summary>
|
||||
/// <param name="fullyQualifiedName">The fully qualified
|
||||
/// method name (e.g. Namespace.ClassName.MethodName).</param>
|
||||
/// <returns>Null if the method cannot be found.</returns>
|
||||
public TestMember GetTestMember(string fullyQualifiedName) |
||||
{ |
||||
string className = TestMember.GetQualifiedClassName(fullyQualifiedName); |
||||
if (className != null) { |
||||
if (Contains(className)) { |
||||
TestClass testClass = this[className]; |
||||
string memberName = TestMember.GetMemberName(fullyQualifiedName); |
||||
if (memberName != null) { |
||||
return testClass.GetTestMember(memberName); |
||||
} |
||||
} else { |
||||
LoggingService.Debug("TestClass not found: " + className); |
||||
} |
||||
} else { |
||||
LoggingService.Debug("Invalid test member name: " + fullyQualifiedName); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
protected override string GetKeyForItem(TestClass item) |
||||
{ |
||||
return item.QualifiedName; |
||||
} |
||||
|
||||
protected override void InsertItem(int index, TestClass item) |
||||
{ |
||||
item.ResultChanged += TestClassResultChanged; |
||||
base.InsertItem(index, item); |
||||
TestClassResultChanged(item, new EventArgs()); |
||||
OnTestClassAdded(item); |
||||
} |
||||
|
||||
protected override void RemoveItem(int index) |
||||
{ |
||||
TestClass c = this[index]; |
||||
c.ResultChanged -= TestClassResultChanged; |
||||
base.RemoveItem(index); |
||||
OnTestResultNone(c.Name); |
||||
OnTestClassRemoved(c); |
||||
} |
||||
|
||||
protected void OnTestClassAdded(TestClass testClass) |
||||
{ |
||||
if (TestClassAdded != null) { |
||||
TestClassAdded(this, new TestClassEventArgs(testClass)); |
||||
} |
||||
} |
||||
|
||||
protected void OnTestClassRemoved(TestClass testClass) |
||||
{ |
||||
if (TestClassRemoved != null) { |
||||
TestClassRemoved(this, new TestClassEventArgs(testClass)); |
||||
} |
||||
} |
||||
|
||||
void TestClassResultChanged(object source, EventArgs e) |
||||
{ |
||||
TestClass c = (TestClass)source; |
||||
switch (c.Result) { |
||||
case TestResultType.None: |
||||
OnTestResultNone(c.QualifiedName); |
||||
break; |
||||
case TestResultType.Failure: |
||||
SetTestResult(TestResultType.Failure); |
||||
failedTestClasses.Add(c.QualifiedName, c); |
||||
break; |
||||
case TestResultType.Success: |
||||
passedTestClasses.Add(c.QualifiedName, c); |
||||
if (passedTestClasses.Count == Count) { |
||||
SetTestResult(TestResultType.Success); |
||||
} else if (passedTestClasses.Count + ignoredTestClasses.Count == Count) { |
||||
SetTestResult(TestResultType.Ignored); |
||||
} |
||||
break; |
||||
case TestResultType.Ignored: |
||||
ignoredTestClasses.Add(c.QualifiedName, c); |
||||
if (ignoredTestClasses.Count == Count || |
||||
ignoredTestClasses.Count + passedTestClasses.Count == Count) { |
||||
SetTestResult(TestResultType.Ignored); |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
|
||||
void SetTestResult(TestResultType value) |
||||
{ |
||||
TestResultType previousTestResult = testResult; |
||||
testResult = value; |
||||
if (testResult != previousTestResult) { |
||||
OnResultChanged(); |
||||
} |
||||
} |
||||
|
||||
void OnResultChanged() |
||||
{ |
||||
if (ResultChanged != null) { |
||||
ResultChanged(this, new EventArgs()); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Removes the specified test class from the list of
|
||||
/// failed, passed and ignored tests and updates the
|
||||
/// test result state of the test class collection.
|
||||
/// </summary>
|
||||
void OnTestResultNone(string qualifiedName) |
||||
{ |
||||
passedTestClasses.Remove(qualifiedName); |
||||
failedTestClasses.Remove(qualifiedName); |
||||
ignoredTestClasses.Remove(qualifiedName); |
||||
if (ignoredTestClasses.Count + failedTestClasses.Count == 0) { |
||||
SetTestResult(TestResultType.None); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the test class from the specified test result.
|
||||
/// </summary>
|
||||
TestClass GetTestClassFromTestMemberName(string memberName) |
||||
{ |
||||
if (memberName != null) { |
||||
string className = TestMember.GetQualifiedClassName(memberName); |
||||
if (className != null) { |
||||
if (Contains(className)) { |
||||
return this[className]; |
||||
} else { |
||||
LoggingService.Debug("TestClass not found: " + className); |
||||
return GetTestClassFromTestMemberName(className); |
||||
} |
||||
} else { |
||||
LoggingService.Debug("Invalid TestMember.Name: " + memberName); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
@ -1,30 +0,0 @@
@@ -1,30 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
/// <summary>
|
||||
/// Represents the class that will handle the TestCollection's
|
||||
/// TestClassAdded or TestClassRemoved events.
|
||||
/// </summary>
|
||||
public delegate void TestClassEventHandler(object source, TestClassEventArgs e); |
||||
|
||||
/// <summary>
|
||||
/// Provides data for the TestCollection's TestClassAdded and TestClassRemoved events.
|
||||
/// </summary>
|
||||
public class TestClassEventArgs |
||||
{ |
||||
TestClass testClass; |
||||
|
||||
public TestClassEventArgs(TestClass testClass) |
||||
{ |
||||
this.testClass = testClass; |
||||
} |
||||
|
||||
public TestClass TestClass { |
||||
get { return testClass; } |
||||
} |
||||
} |
||||
} |
||||
@ -1,108 +0,0 @@
@@ -1,108 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public abstract class TestDebuggerBase : TestRunnerBase |
||||
{ |
||||
IUnitTestDebuggerService debuggerService; |
||||
IUnitTestMessageService messageService; |
||||
IDebugger debugger; |
||||
ITestResultsMonitor testResultsMonitor; |
||||
|
||||
public TestDebuggerBase() |
||||
: this(new UnitTestDebuggerService(), |
||||
new UnitTestMessageService(), |
||||
new TestResultsMonitor()) |
||||
{ |
||||
} |
||||
|
||||
public TestDebuggerBase(IUnitTestDebuggerService debuggerService, |
||||
IUnitTestMessageService messageService, |
||||
ITestResultsMonitor testResultsMonitor) |
||||
{ |
||||
this.debuggerService = debuggerService; |
||||
this.messageService = messageService; |
||||
this.testResultsMonitor = testResultsMonitor; |
||||
this.debugger = debuggerService.CurrentDebugger; |
||||
|
||||
testResultsMonitor.TestFinished += OnTestFinished; |
||||
} |
||||
|
||||
protected ITestResultsMonitor TestResultsMonitor { |
||||
get { return testResultsMonitor; } |
||||
} |
||||
|
||||
public override void Start(SelectedTests selectedTests) |
||||
{ |
||||
ProcessStartInfo startInfo = GetProcessStartInfo(selectedTests); |
||||
if (IsDebuggerRunning) { |
||||
if (CanStopDebugging()) { |
||||
debugger.Stop(); |
||||
Start(startInfo); |
||||
} |
||||
} else { |
||||
Start(startInfo); |
||||
} |
||||
} |
||||
|
||||
public bool IsDebuggerRunning { |
||||
get { return debuggerService.IsDebuggerLoaded && debugger.IsDebugging; } |
||||
} |
||||
|
||||
bool CanStopDebugging() |
||||
{ |
||||
string question = "${res:XML.MainMenu.RunMenu.Compile.StopDebuggingQuestion}"; |
||||
string caption = "${res:XML.MainMenu.RunMenu.Compile.StopDebuggingTitle}"; |
||||
return messageService.AskQuestion(question, caption); |
||||
} |
||||
|
||||
void Start(ProcessStartInfo startInfo) |
||||
{ |
||||
testResultsMonitor.Start(); |
||||
StartDebugger(startInfo); |
||||
} |
||||
|
||||
void StartDebugger(ProcessStartInfo startInfo) |
||||
{ |
||||
LogCommandLine(startInfo); |
||||
|
||||
bool running = false; |
||||
debugger.DebugStopped += DebugStopped; |
||||
try { |
||||
debugger.Start(startInfo); |
||||
running = true; |
||||
} finally { |
||||
if (!running) { |
||||
debugger.DebugStopped -= DebugStopped; |
||||
} |
||||
} |
||||
} |
||||
|
||||
void DebugStopped(object source, EventArgs e) |
||||
{ |
||||
debugger.DebugStopped -= DebugStopped; |
||||
OnAllTestsFinished(source, e); |
||||
} |
||||
|
||||
public override void Stop() |
||||
{ |
||||
if (debugger.IsDebugging) { |
||||
debugger.Stop(); |
||||
} |
||||
|
||||
testResultsMonitor.Stop(); |
||||
testResultsMonitor.Read(); |
||||
} |
||||
|
||||
public override void Dispose() |
||||
{ |
||||
Stop(); |
||||
testResultsMonitor.Dispose(); |
||||
} |
||||
} |
||||
} |
||||
@ -1,23 +0,0 @@
@@ -1,23 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public delegate void TestFinishedEventHandler(object source, TestFinishedEventArgs e); |
||||
|
||||
public class TestFinishedEventArgs : EventArgs |
||||
{ |
||||
TestResult result; |
||||
|
||||
public TestFinishedEventArgs(TestResult result) |
||||
{ |
||||
this.result = result; |
||||
} |
||||
|
||||
public TestResult Result { |
||||
get { return result; } |
||||
} |
||||
} |
||||
} |
||||
@ -1,90 +0,0 @@
@@ -1,90 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.IO; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class TestFrameworkDescriptor |
||||
{ |
||||
Properties properties; |
||||
ITestFrameworkFactory factory; |
||||
ITestFramework testFramework; |
||||
List<string> supportedProjectFileExtensions = new List<string>(); |
||||
|
||||
public TestFrameworkDescriptor(Properties properties, ITestFrameworkFactory factory) |
||||
{ |
||||
this.properties = properties; |
||||
this.factory = factory; |
||||
|
||||
GetSupportedProjectFileExtensions(); |
||||
} |
||||
|
||||
void GetSupportedProjectFileExtensions() |
||||
{ |
||||
string extensions = properties["supportedProjects"]; |
||||
|
||||
foreach (string extension in extensions.Split(';')) { |
||||
supportedProjectFileExtensions.Add(extension.ToLowerInvariant().Trim()); |
||||
} |
||||
} |
||||
|
||||
public string Id { |
||||
get { return properties["id"]; } |
||||
} |
||||
|
||||
public ITestFramework TestFramework { |
||||
get { |
||||
CreateTestFrameworkIfNotCreated(); |
||||
return testFramework; |
||||
} |
||||
} |
||||
|
||||
void CreateTestFrameworkIfNotCreated() |
||||
{ |
||||
if (testFramework == null) { |
||||
testFramework = factory.Create(ClassName); |
||||
} |
||||
} |
||||
|
||||
string ClassName { |
||||
get { return properties["class"]; } |
||||
} |
||||
|
||||
public bool IsSupportedProject(IProject project) |
||||
{ |
||||
if (IsSupportedProjectFileExtension(project)) { |
||||
return IsSupportedByTestFramework(project); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
bool IsSupportedProjectFileExtension(IProject project) |
||||
{ |
||||
string extension = GetProjectFileExtension(project); |
||||
return IsSupportedProjectFileExtension(extension); |
||||
} |
||||
|
||||
string GetProjectFileExtension(IProject project) |
||||
{ |
||||
if (project != null) { |
||||
return Path.GetExtension(project.FileName).ToLowerInvariant(); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
bool IsSupportedProjectFileExtension(string extension) |
||||
{ |
||||
return supportedProjectFileExtensions.Contains(extension); |
||||
} |
||||
|
||||
bool IsSupportedByTestFramework(IProject project) |
||||
{ |
||||
return TestFramework.IsTestProject(project); |
||||
} |
||||
} |
||||
} |
||||
@ -1,30 +0,0 @@
@@ -1,30 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections; |
||||
using ICSharpCode.Core; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class TestFrameworkDoozer : IDoozer |
||||
{ |
||||
public TestFrameworkDoozer() |
||||
{ |
||||
} |
||||
|
||||
public bool HandleConditions { |
||||
get { return false; } |
||||
} |
||||
|
||||
public object BuildItem(BuildItemArgs args) |
||||
{ |
||||
return BuildItem(args.Codon, new TestFrameworkFactory(args.AddIn)); |
||||
} |
||||
|
||||
public TestFrameworkDescriptor BuildItem(Codon codon, ITestFrameworkFactory factory) |
||||
{ |
||||
return new TestFrameworkDescriptor(codon.Properties, factory); |
||||
} |
||||
} |
||||
} |
||||
@ -1,23 +0,0 @@
@@ -1,23 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.Core; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class TestFrameworkFactory : ITestFrameworkFactory |
||||
{ |
||||
AddIn addin; |
||||
|
||||
public TestFrameworkFactory(AddIn addin) |
||||
{ |
||||
this.addin = addin; |
||||
} |
||||
|
||||
public ITestFramework Create(string className) |
||||
{ |
||||
return addin.CreateObject(className) as ITestFramework; |
||||
} |
||||
} |
||||
} |
||||
@ -1,153 +0,0 @@
@@ -1,153 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Collections.ObjectModel; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class TestMemberCollection : KeyedCollection<string, TestMember> |
||||
{ |
||||
TestResultType testResult = TestResultType.None; |
||||
Dictionary<string, TestMember> passedTestMembers = new Dictionary<string, TestMember>(); |
||||
Dictionary<string, TestMember> failedTestMembers = new Dictionary<string, TestMember>(); |
||||
Dictionary<string, TestMember> ignoredTestMembers = new Dictionary<string, TestMember>(); |
||||
|
||||
/// <summary>
|
||||
/// Raised when the test result for this collection of
|
||||
/// members has changed.
|
||||
/// </summary>
|
||||
public event EventHandler ResultChanged; |
||||
|
||||
/// <summary>
|
||||
/// Raised when a member is added to this collection.
|
||||
/// </summary>
|
||||
public event TestMemberEventHandler TestMemberAdded; |
||||
|
||||
/// <summary>
|
||||
/// Raised when a member is removed from this collection.
|
||||
/// </summary>
|
||||
public event TestMemberEventHandler TestMemberRemoved; |
||||
|
||||
/// <summary>
|
||||
/// Gets the overall test results for the collection of
|
||||
/// test members.
|
||||
/// </summary>
|
||||
public TestResultType Result { |
||||
get { return testResult; } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Sets all the test members test results back to none.
|
||||
/// </summary>
|
||||
public void ResetTestResults() |
||||
{ |
||||
passedTestMembers.Clear(); |
||||
failedTestMembers.Clear(); |
||||
ignoredTestMembers.Clear(); |
||||
|
||||
foreach (TestMember member in this) { |
||||
member.Result = TestResultType.None; |
||||
} |
||||
|
||||
SetTestResult(TestResultType.None); |
||||
} |
||||
|
||||
protected override void InsertItem(int index, TestMember item) |
||||
{ |
||||
item.ResultChanged += TestMemberResultChanged; |
||||
base.InsertItem(index, item); |
||||
TestMemberResultChanged(item, new EventArgs()); |
||||
OnTestMemberAdded(item); |
||||
} |
||||
|
||||
protected override string GetKeyForItem(TestMember item) |
||||
{ |
||||
return item.Name; |
||||
} |
||||
|
||||
protected override void RemoveItem(int index) |
||||
{ |
||||
TestMember member = this[index]; |
||||
member.ResultChanged -= TestMemberResultChanged; |
||||
base.RemoveItem(index); |
||||
OnTestResultNone(member.Name); |
||||
OnTestMemberRemoved(member); |
||||
} |
||||
|
||||
protected void OnTestMemberAdded(TestMember testMember) |
||||
{ |
||||
if (TestMemberAdded != null) { |
||||
TestMemberAdded(this, new TestMemberEventArgs(testMember)); |
||||
} |
||||
} |
||||
|
||||
protected void OnTestMemberRemoved(TestMember testMember) |
||||
{ |
||||
if (TestMemberRemoved != null) { |
||||
TestMemberRemoved(this, new TestMemberEventArgs(testMember)); |
||||
} |
||||
} |
||||
|
||||
void TestMemberResultChanged(object source, EventArgs e) |
||||
{ |
||||
TestMember member = (TestMember)source; |
||||
switch (member.Result) { |
||||
case TestResultType.None: |
||||
OnTestResultNone(member.Name); |
||||
break; |
||||
case TestResultType.Failure: |
||||
SetTestResult(TestResultType.Failure); |
||||
failedTestMembers.Add(member.Name, member); |
||||
break; |
||||
case TestResultType.Success: |
||||
passedTestMembers.Add(member.Name, member); |
||||
if (passedTestMembers.Count == Count) { |
||||
SetTestResult(TestResultType.Success); |
||||
} else if (passedTestMembers.Count + ignoredTestMembers.Count == Count) { |
||||
SetTestResult(TestResultType.Ignored); |
||||
} |
||||
break; |
||||
case TestResultType.Ignored: |
||||
ignoredTestMembers.Add(member.Name, member); |
||||
if (ignoredTestMembers.Count == Count || |
||||
ignoredTestMembers.Count + passedTestMembers.Count == Count) { |
||||
SetTestResult(TestResultType.Ignored); |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
|
||||
void SetTestResult(TestResultType value) |
||||
{ |
||||
TestResultType previousTestResult = testResult; |
||||
testResult = value; |
||||
if (testResult != previousTestResult) { |
||||
OnResultChanged(); |
||||
} |
||||
} |
||||
|
||||
void OnResultChanged() |
||||
{ |
||||
if (ResultChanged != null) { |
||||
ResultChanged(this, new EventArgs()); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Removes the specified test member from the list of
|
||||
/// failed, passed and ignored tests and updates the
|
||||
/// test result state of the test members collection.
|
||||
/// </summary>
|
||||
void OnTestResultNone(string name) |
||||
{ |
||||
passedTestMembers.Remove(name); |
||||
failedTestMembers.Remove(name); |
||||
ignoredTestMembers.Remove(name); |
||||
if (ignoredTestMembers.Count + failedTestMembers.Count == 0) { |
||||
SetTestResult(TestResultType.None); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,30 +0,0 @@
@@ -1,30 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
/// <summary>
|
||||
/// Represents the member that will handle the TestCollection's
|
||||
/// TestMemberAdded or TestMemberRemoved events.
|
||||
/// </summary>
|
||||
public delegate void TestMemberEventHandler(object source, TestMemberEventArgs e); |
||||
|
||||
/// <summary>
|
||||
/// Provides data for the TestCollection's TestMemberAdded and TestMemberRemoved events.
|
||||
/// </summary>
|
||||
public class TestMemberEventArgs |
||||
{ |
||||
TestMember testMember; |
||||
|
||||
public TestMemberEventArgs(TestMember testMember) |
||||
{ |
||||
this.testMember = testMember; |
||||
} |
||||
|
||||
public TestMember TestMember { |
||||
get { return testMember; } |
||||
} |
||||
} |
||||
} |
||||
@ -1,55 +0,0 @@
@@ -1,55 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
/// <summary>
|
||||
/// Represents a method that has the [Test] attribute associated with it.
|
||||
/// </summary>
|
||||
public class TestMethodTreeNode : TestTreeNode |
||||
{ |
||||
TestMethod testMethod; |
||||
|
||||
public TestMethodTreeNode(TestProject project, TestMethod testMethod) |
||||
: base(project, testMethod.Name) |
||||
{ |
||||
this.testMethod = testMethod; |
||||
testMethod.ResultChanged += TestMethodResultChanged; |
||||
UpdateImageListIndex(testMethod.Result); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the underlying IMethod for this test method.
|
||||
/// </summary>
|
||||
public IMember Method { |
||||
get { |
||||
return testMethod.Method; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Removes the TestMethod.ResultChanged event handler.
|
||||
/// </summary>
|
||||
public override void Dispose() |
||||
{ |
||||
if (!IsDisposed) { |
||||
testMethod.ResultChanged -= TestMethodResultChanged; |
||||
} |
||||
base.Dispose(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Updates the node's icon after the test method result
|
||||
/// has changed.
|
||||
/// </summary>
|
||||
void TestMethodResultChanged(object source, EventArgs e) |
||||
{ |
||||
UpdateImageListIndex(testMethod.Result); |
||||
} |
||||
} |
||||
} |
||||
@ -1,109 +0,0 @@
@@ -1,109 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
using ICSharpCode.Core.WinForms; |
||||
using ICSharpCode.SharpDevelop.Util; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class TestProcessRunnerBase : TestRunnerBase |
||||
{ |
||||
IUnitTestProcessRunner processRunner; |
||||
ITestResultsMonitor testResultsMonitor; |
||||
IFileSystem fileSystem; |
||||
IUnitTestMessageService messageService; |
||||
|
||||
public TestProcessRunnerBase() |
||||
: this(new UnitTestProcessRunner(), |
||||
new TestResultsMonitor(), |
||||
new UnitTestFileService(), |
||||
new UnitTestMessageService()) |
||||
{ |
||||
} |
||||
|
||||
public TestProcessRunnerBase(TestProcessRunnerBaseContext context) |
||||
: this(context.TestProcessRunner, |
||||
context.TestResultsMonitor, |
||||
context.FileSystem, |
||||
context.MessageService) |
||||
{ |
||||
} |
||||
|
||||
public TestProcessRunnerBase(IUnitTestProcessRunner processRunner, |
||||
ITestResultsMonitor testResultsMonitor, |
||||
IFileSystem fileSystem, |
||||
IUnitTestMessageService messageService) |
||||
{ |
||||
this.processRunner = processRunner; |
||||
this.testResultsMonitor = testResultsMonitor; |
||||
this.fileSystem = fileSystem; |
||||
this.messageService = messageService; |
||||
|
||||
processRunner.LogStandardOutputAndError = false; |
||||
processRunner.OutputLineReceived += OutputLineReceived; |
||||
processRunner.ErrorLineReceived += OutputLineReceived; |
||||
processRunner.ProcessExited += OnAllTestsFinished; |
||||
testResultsMonitor.TestFinished += OnTestFinished; |
||||
} |
||||
|
||||
protected ITestResultsMonitor TestResultsMonitor { |
||||
get { return testResultsMonitor; } |
||||
} |
||||
|
||||
protected IUnitTestProcessRunner ProcessRunner { |
||||
get { return processRunner; } |
||||
} |
||||
|
||||
void OutputLineReceived(object source, LineReceivedEventArgs e) |
||||
{ |
||||
OnMessageReceived(e.Line); |
||||
} |
||||
|
||||
public override void Start(SelectedTests selectedTests) |
||||
{ |
||||
ProcessStartInfo startInfo = GetProcessStartInfo(selectedTests); |
||||
Start(startInfo); |
||||
} |
||||
|
||||
void Start(ProcessStartInfo processStartInfo) |
||||
{ |
||||
LogCommandLine(processStartInfo); |
||||
|
||||
if (ApplicationFileNameExists(processStartInfo.FileName)) { |
||||
testResultsMonitor.Start(); |
||||
processRunner.WorkingDirectory = processStartInfo.WorkingDirectory; |
||||
processRunner.Start(processStartInfo.FileName, processStartInfo.Arguments); |
||||
} else { |
||||
ShowApplicationDoesNotExistMessage(processStartInfo.FileName); |
||||
} |
||||
} |
||||
|
||||
bool ApplicationFileNameExists(string fileName) |
||||
{ |
||||
return fileSystem.FileExists(fileName); |
||||
} |
||||
|
||||
void ShowApplicationDoesNotExistMessage(string fileName) |
||||
{ |
||||
string resourceString = "${res:ICSharpCode.UnitTesting.TestRunnerNotFoundMessageFormat}"; |
||||
messageService.ShowFormattedErrorMessage(resourceString, fileName); |
||||
} |
||||
|
||||
public override void Stop() |
||||
{ |
||||
processRunner.Kill(); |
||||
testResultsMonitor.Stop(); |
||||
testResultsMonitor.Read(); |
||||
} |
||||
|
||||
public override void Dispose() |
||||
{ |
||||
testResultsMonitor.Dispose(); |
||||
testResultsMonitor.TestFinished -= OnTestFinished; |
||||
processRunner.ErrorLineReceived -= OutputLineReceived; |
||||
processRunner.OutputLineReceived -= OutputLineReceived; |
||||
} |
||||
} |
||||
} |
||||
@ -1,52 +0,0 @@
@@ -1,52 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.Core.WinForms; |
||||
using ICSharpCode.SharpDevelop.Util; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class TestProcessRunnerBaseContext |
||||
{ |
||||
IUnitTestProcessRunner processRunner; |
||||
ITestResultsMonitor testResultsMonitor; |
||||
IFileSystem fileSystem; |
||||
IUnitTestMessageService messageService; |
||||
|
||||
public TestProcessRunnerBaseContext() |
||||
: this(new UnitTestProcessRunner(), |
||||
new TestResultsMonitor(), |
||||
new UnitTestFileService(), |
||||
new UnitTestMessageService()) |
||||
{ |
||||
} |
||||
|
||||
public TestProcessRunnerBaseContext(IUnitTestProcessRunner processRunner, |
||||
ITestResultsMonitor testResultsMonitor, |
||||
IFileSystem fileSystem, |
||||
IUnitTestMessageService messageService) |
||||
{ |
||||
this.processRunner = processRunner; |
||||
this.testResultsMonitor = testResultsMonitor; |
||||
this.fileSystem = fileSystem; |
||||
this.messageService = messageService; |
||||
} |
||||
|
||||
public IUnitTestProcessRunner TestProcessRunner { |
||||
get { return processRunner; } |
||||
} |
||||
|
||||
public ITestResultsMonitor TestResultsMonitor { |
||||
get { return testResultsMonitor; } |
||||
} |
||||
|
||||
public IFileSystem FileSystem { |
||||
get { return fileSystem; } |
||||
} |
||||
|
||||
public IUnitTestMessageService MessageService { |
||||
get { return messageService; } |
||||
} |
||||
} |
||||
} |
||||
@ -1,178 +0,0 @@
@@ -1,178 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.IO; |
||||
using System.Text; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
/// <summary>
|
||||
/// Watches for new test results as they occur. Test results
|
||||
/// are written to a file and read in by this class.
|
||||
/// </summary>
|
||||
public class TestResultsMonitor : ITestResultsMonitor |
||||
{ |
||||
FileInfo fileInfo; |
||||
TestResultsReader testResultsReader; |
||||
FileSystemWatcher fileSystemWatcher; |
||||
|
||||
long initialFilePosition = 3; |
||||
long filePosition; |
||||
|
||||
const int BytesBufferLength = 1024; |
||||
byte[] bytes = new byte[BytesBufferLength]; |
||||
|
||||
/// <summary>
|
||||
/// Raised when a single test has been completed.
|
||||
/// </summary>
|
||||
public event TestFinishedEventHandler TestFinished; |
||||
|
||||
public TestResultsMonitor(string fileName) |
||||
{ |
||||
fileInfo = new FileInfo(fileName); |
||||
ResetFilePosition(); |
||||
} |
||||
|
||||
public TestResultsMonitor() |
||||
: this(Path.GetTempFileName()) |
||||
{ |
||||
ResetFilePosition(); |
||||
} |
||||
|
||||
public long InitialFilePosition { |
||||
get { return initialFilePosition; } |
||||
set { initialFilePosition = value; } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the test results filename.
|
||||
/// </summary>
|
||||
public string FileName { |
||||
get { return fileInfo.FullName; } |
||||
set { fileInfo = new FileInfo(value); } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Starts monitoring for test results.
|
||||
/// </summary>
|
||||
public void Start() |
||||
{ |
||||
testResultsReader = new TestResultsReader(); |
||||
ResetFilePosition(); |
||||
|
||||
string filter = fileInfo.Name; |
||||
fileSystemWatcher = new FileSystemWatcher(fileInfo.DirectoryName, filter); |
||||
|
||||
if (File.Exists(fileInfo.FullName)) { |
||||
fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite; |
||||
fileSystemWatcher.Changed += FileChanged; |
||||
} else { |
||||
fileSystemWatcher.Created += FileCreated; |
||||
} |
||||
fileSystemWatcher.Error += FileSystemWatcherError; |
||||
fileSystemWatcher.EnableRaisingEvents = true; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Stops monitoring.
|
||||
/// </summary>
|
||||
public void Stop() |
||||
{ |
||||
if (fileSystemWatcher != null) { |
||||
fileSystemWatcher.Dispose(); |
||||
fileSystemWatcher = null; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Reads the rest of the file from the current position.
|
||||
/// Raises the TestFinished event for each test result
|
||||
/// still in the file.
|
||||
/// </summary>
|
||||
public void Read() |
||||
{ |
||||
string text = ReadTextAdded(); |
||||
if (text != null) { |
||||
TestResult[] results = testResultsReader.Read(text); |
||||
OnTestResultsReceived(results); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Stops monitoring and releases any resources used
|
||||
/// by the TestResultsMonitor.
|
||||
/// </summary>
|
||||
public void Dispose() |
||||
{ |
||||
Stop(); |
||||
|
||||
try { |
||||
File.Delete(FileName); |
||||
} catch { } |
||||
} |
||||
|
||||
void FileCreated(object source, FileSystemEventArgs e) |
||||
{ |
||||
fileSystemWatcher.Created -= FileCreated; |
||||
fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite; |
||||
fileSystemWatcher.Changed += FileChanged; |
||||
} |
||||
|
||||
void FileChanged(object source, FileSystemEventArgs e) |
||||
{ |
||||
Read(); |
||||
} |
||||
|
||||
void OnTestResultsReceived(TestResult[] results) |
||||
{ |
||||
if ((results.Length > 0) && (TestFinished != null)) { |
||||
foreach (TestResult result in results) { |
||||
TestFinished(this, new TestFinishedEventArgs(result)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Reads the text added to the end of the file from the last
|
||||
/// position we read from.
|
||||
/// </summary>
|
||||
string ReadTextAdded() |
||||
{ |
||||
StringBuilder text = null; |
||||
try { |
||||
using (FileStream fs = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { |
||||
if (fs.Length > 0) { |
||||
text = new StringBuilder(); |
||||
int bytesRead = 0; |
||||
fs.Seek(filePosition, SeekOrigin.Begin); |
||||
do { |
||||
bytesRead = fs.Read(bytes, 0, BytesBufferLength); |
||||
if (bytesRead > 0) { |
||||
filePosition += bytesRead; |
||||
text.Append(UTF8Encoding.UTF8.GetString(bytes, 0, bytesRead)); |
||||
} |
||||
} while ((bytesRead > 0) && (filePosition < fs.Length)); |
||||
} |
||||
} |
||||
} catch (FileNotFoundException) { |
||||
// Test was aborted before it even started execution
|
||||
return null; |
||||
} |
||||
if (text != null) { |
||||
return text.ToString(); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
void FileSystemWatcherError(object source, ErrorEventArgs e) |
||||
{ |
||||
Console.WriteLine(e.GetException().ToString()); |
||||
} |
||||
|
||||
void ResetFilePosition() |
||||
{ |
||||
filePosition = initialFilePosition; |
||||
} |
||||
} |
||||
} |
||||
@ -1,155 +0,0 @@
@@ -1,155 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Text; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
/// <summary>
|
||||
/// Reads the test results file produced by the custom
|
||||
/// nunit-console application.
|
||||
/// </summary>
|
||||
public class TestResultsReader |
||||
{ |
||||
StringBuilder nameBuilder = new StringBuilder(); |
||||
StringBuilder valueBuilder = new StringBuilder(); |
||||
bool firstNameChar = true; |
||||
TestResult result; |
||||
|
||||
enum State { |
||||
WaitingForEndOfName = 0, |
||||
WaitingForStartOfValue = 1, |
||||
WaitingForEndOfValue = 2 |
||||
} |
||||
|
||||
State state = State.WaitingForEndOfName; |
||||
|
||||
public TestResultsReader() |
||||
{ |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Returns any TestResults that are in the text.
|
||||
/// </summary>
|
||||
/// <param name="text">The text read in from the
|
||||
/// TestResults file.</param>
|
||||
public TestResult[] Read(string text) |
||||
{ |
||||
List<TestResult> results = new List<TestResult>(); |
||||
foreach (char ch in text) { |
||||
if (ReadNameValuePair(ch)) { |
||||
if (ReadTestResult()) { |
||||
results.Add(result); |
||||
} |
||||
} |
||||
} |
||||
return results.ToArray(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Reads a name-value pair of the form:
|
||||
///
|
||||
/// Name: Value
|
||||
///
|
||||
/// A value can span multiple lines:
|
||||
///
|
||||
/// Name1: ValueLine1
|
||||
/// {SP}ValueLine2
|
||||
/// {SP}ValueLine3
|
||||
/// Name1: Value2
|
||||
///
|
||||
/// Each continued line of the value must start with
|
||||
/// a single space character to distinguish it from
|
||||
/// the start of a new name-value pair.
|
||||
/// </summary>
|
||||
/// <returns>True if a name-value pair has been
|
||||
/// successfully read in</returns>
|
||||
bool ReadNameValuePair(char ch) |
||||
{ |
||||
if (state == State.WaitingForEndOfName) { |
||||
ReadNameChar(ch); |
||||
} else if (state == State.WaitingForStartOfValue) { |
||||
// Makes sure first space is ignored.
|
||||
state = State.WaitingForEndOfValue; |
||||
} else { |
||||
return ReadValueChar(ch); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
void ReadNameChar(char ch) |
||||
{ |
||||
if (ch == ':') { |
||||
state = State.WaitingForStartOfValue; |
||||
} else if (ch == '\r' || ch == '\n') { |
||||
nameBuilder = new StringBuilder(); |
||||
} else if (ch == ' ' && firstNameChar) { |
||||
state = State.WaitingForEndOfValue; |
||||
valueBuilder.Append("\r\n"); |
||||
} else if (firstNameChar) { |
||||
firstNameChar = false; |
||||
nameBuilder = new StringBuilder(); |
||||
valueBuilder = new StringBuilder(); |
||||
nameBuilder.Append(ch); |
||||
} else { |
||||
nameBuilder.Append(ch); |
||||
} |
||||
} |
||||
|
||||
bool ReadValueChar(char ch) |
||||
{ |
||||
if (ch == '\r') { |
||||
// Ignore.
|
||||
} else if (ch == '\n') { |
||||
state = State.WaitingForEndOfName; |
||||
firstNameChar = true; |
||||
return true; |
||||
} else { |
||||
valueBuilder.Append(ch); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Creates and updates a TestResult based on the
|
||||
/// name-value pair read in,
|
||||
/// </summary>
|
||||
/// <returns>True if a TestResult is ready to be returned
|
||||
/// to the caller.</returns>
|
||||
/// <remarks>
|
||||
/// The first name-value pair for a test result is the
|
||||
/// test name. The last name-value pair is the result of
|
||||
/// the test (Success, Failure or Ignored).</remarks>
|
||||
bool ReadTestResult() |
||||
{ |
||||
string name = nameBuilder.ToString(); |
||||
if (name == "Name") { |
||||
result = new TestResult(valueBuilder.ToString()); |
||||
} else if (result != null) { |
||||
if (name == "Message") { |
||||
result.Message = valueBuilder.ToString(); |
||||
} else if (name == "StackTrace") { |
||||
result.StackTrace = valueBuilder.ToString(); |
||||
} else if (name == "Result") { |
||||
UpdateTestSuccess(); |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
void UpdateTestSuccess() |
||||
{ |
||||
string value = valueBuilder.ToString(); |
||||
if (value == "Success") { |
||||
result.ResultType = TestResultType.Success; |
||||
} else if (value == "Failure") { |
||||
result.ResultType = TestResultType.Failure; |
||||
} else { |
||||
result.ResultType = TestResultType.Ignored; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,68 +0,0 @@
@@ -1,68 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public abstract class TestRunnerBase : ITestRunner |
||||
{ |
||||
public TestRunnerBase() |
||||
{ |
||||
} |
||||
|
||||
protected virtual ProcessStartInfo GetProcessStartInfo(SelectedTests selectedTests) |
||||
{ |
||||
return new ProcessStartInfo(); |
||||
} |
||||
|
||||
protected void LogCommandLine(ProcessStartInfo startInfo) |
||||
{ |
||||
string commandLine = GetCommandLine(startInfo); |
||||
OnMessageReceived(commandLine); |
||||
} |
||||
|
||||
protected string GetCommandLine(ProcessStartInfo startInfo) |
||||
{ |
||||
return String.Format("\"{0}\" {1}", startInfo.FileName, startInfo.Arguments); |
||||
} |
||||
|
||||
public event EventHandler AllTestsFinished; |
||||
|
||||
protected void OnAllTestsFinished(object source, EventArgs e) |
||||
{ |
||||
if (AllTestsFinished != null) { |
||||
AllTestsFinished(source, e); |
||||
} |
||||
} |
||||
|
||||
public event TestFinishedEventHandler TestFinished; |
||||
|
||||
protected void OnTestFinished(object source, TestFinishedEventArgs e) |
||||
{ |
||||
if (TestFinished != null) { |
||||
TestResult testResult = CreateTestResultForTestFramework(e.Result); |
||||
TestFinished(source, new TestFinishedEventArgs(testResult)); |
||||
} |
||||
} |
||||
|
||||
protected virtual TestResult CreateTestResultForTestFramework(TestResult testResult) |
||||
{ |
||||
return testResult; |
||||
} |
||||
|
||||
public event MessageReceivedEventHandler MessageReceived; |
||||
|
||||
protected virtual void OnMessageReceived(string message) |
||||
{ |
||||
if (MessageReceived != null) { |
||||
MessageReceived(this, new MessageReceivedEventArgs(message)); |
||||
} |
||||
} |
||||
|
||||
public abstract void Dispose(); |
||||
public abstract void Stop(); |
||||
public abstract void Start(SelectedTests selectedTests); |
||||
} |
||||
} |
||||
@ -1,47 +0,0 @@
@@ -1,47 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public static class TestService |
||||
{ |
||||
static IRegisteredTestFrameworks testFrameworks; |
||||
static MessageViewCategory unitTestMessageView; |
||||
|
||||
public static IRegisteredTestFrameworks RegisteredTestFrameworks { |
||||
get { |
||||
CreateRegisteredTestFrameworks(); |
||||
return testFrameworks; |
||||
} |
||||
set { testFrameworks = value; } |
||||
} |
||||
|
||||
static void CreateRegisteredTestFrameworks() |
||||
{ |
||||
if (testFrameworks == null) { |
||||
UnitTestAddInTree addInTree = new UnitTestAddInTree(); |
||||
testFrameworks = new RegisteredTestFrameworks(addInTree); |
||||
} |
||||
} |
||||
|
||||
public static MessageViewCategory UnitTestMessageView { |
||||
get { |
||||
if (unitTestMessageView == null) { |
||||
CreateUnitTestCategory(); |
||||
} |
||||
return unitTestMessageView; |
||||
} |
||||
} |
||||
|
||||
static void CreateUnitTestCategory() |
||||
{ |
||||
MessageViewCategory.Create(ref unitTestMessageView, |
||||
"UnitTesting", |
||||
"${res:ICSharpCode.NUnitPad.NUnitPadContent.PadName}"); |
||||
} |
||||
|
||||
} |
||||
} |
||||
@ -1,17 +0,0 @@
@@ -1,17 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using ICSharpCode.Core; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class UnitTestAddInTree : IAddInTree |
||||
{ |
||||
public List<T> BuildItems<T>(string path, object caller) |
||||
{ |
||||
return AddInTree.BuildItems<T>(path, caller); |
||||
} |
||||
} |
||||
} |
||||
@ -1,221 +0,0 @@
@@ -1,221 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.IO; |
||||
using System.Text; |
||||
|
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
/// <summary>
|
||||
/// Helper to run the unit testing console application.
|
||||
/// </summary>
|
||||
public class UnitTestApplicationStartHelper |
||||
{ |
||||
/// <summary>
|
||||
/// returns full/path/to/Tools/NUnit
|
||||
/// </summary>
|
||||
public static string UnitTestApplicationDirectory { |
||||
get { |
||||
return Path.Combine(FileUtility.ApplicationRootPath, @"bin\Tools\NUnit"); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// returns full/path/to/Tools/NUnit/nunit-console.exe (or whichever nunit-console exe is right
|
||||
/// for the project - there are different .exes for .NET 4.0 and for x86-only projects.
|
||||
/// </summary>
|
||||
public string UnitTestApplication { |
||||
get { |
||||
string exe = "nunit-console"; |
||||
if (ProjectUsesDotnet20Runtime(project)) { |
||||
exe += "-dotnet2"; |
||||
} |
||||
if (IsPlatformTarget32Bit(project)) { |
||||
exe += "-x86"; |
||||
} |
||||
exe += ".exe"; |
||||
return Path.Combine(UnitTestApplicationDirectory, exe); |
||||
} |
||||
} |
||||
|
||||
public readonly List<string> Assemblies = new List<string>(); |
||||
|
||||
/// <summary>
|
||||
/// Use shadow copy assemblies. Default = true.
|
||||
/// </summary>
|
||||
public bool ShadowCopy = true; |
||||
|
||||
/// <summary>
|
||||
/// Disables the use of a separate thread to run tests on separate thread. Default = false;
|
||||
/// </summary>
|
||||
public bool NoThread = false; |
||||
|
||||
/// <summary>
|
||||
/// Use /nologo directive.
|
||||
/// </summary>
|
||||
public bool NoLogo = false; |
||||
|
||||
/// <summary>
|
||||
/// Use /labels directive.
|
||||
/// </summary>
|
||||
public bool Labels = false; |
||||
|
||||
/// <summary>
|
||||
/// Use /nodots directive.
|
||||
/// </summary>
|
||||
public bool NoDots = false; |
||||
|
||||
/// <summary>
|
||||
/// File to write xml output to. Default = null.
|
||||
/// </summary>
|
||||
public string XmlOutputFile; |
||||
|
||||
/// <summary>
|
||||
/// Fixture to test. Null = test all fixtures.
|
||||
/// </summary>
|
||||
public string Fixture; |
||||
|
||||
/// <summary>
|
||||
/// Test to run. Null = run all tests. Only valid together with the Fixture property.
|
||||
/// </summary>
|
||||
public string Test; |
||||
|
||||
/// <summary>
|
||||
/// File to write test results to.
|
||||
/// </summary>
|
||||
public string Results; |
||||
|
||||
/// <summary>
|
||||
/// The namespace that tests need to be a part of if they are to
|
||||
/// be run.
|
||||
/// </summary>
|
||||
public string NamespaceFilter; |
||||
|
||||
IProject project; |
||||
|
||||
public void Initialize(IProject project, IClass fixture, IMember test) |
||||
{ |
||||
Initialize(project, null, fixture, test); |
||||
} |
||||
|
||||
public void Initialize(IProject project, string namespaceFilter) |
||||
{ |
||||
Initialize(project, namespaceFilter, null, null); |
||||
} |
||||
|
||||
public void Initialize(IProject project, string namespaceFilter, IClass fixture, IMember test) |
||||
{ |
||||
this.project = project; |
||||
Assemblies.Add(project.OutputAssemblyFullPath); |
||||
if (namespaceFilter != null) { |
||||
NamespaceFilter = namespaceFilter; |
||||
} |
||||
if (fixture != null) { |
||||
Fixture = fixture.DotNetName; |
||||
if (test != null) { |
||||
Test = test.Name; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public IProject Project { |
||||
get { |
||||
return project; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the full command line to run the unit test application.
|
||||
/// This is the combination of the UnitTestApplication and
|
||||
/// the command line arguments.
|
||||
/// </summary>
|
||||
public string GetCommandLine() |
||||
{ |
||||
return String.Concat("\"", UnitTestApplication, "\" ", GetArguments()); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the arguments to use on the command line to run NUnit.
|
||||
/// </summary>
|
||||
public string GetArguments() |
||||
{ |
||||
StringBuilder b = new StringBuilder(); |
||||
foreach (string assembly in Assemblies) { |
||||
if (b.Length > 0) |
||||
b.Append(' '); |
||||
b.Append('"'); |
||||
b.Append(assembly); |
||||
b.Append('"'); |
||||
} |
||||
if (!ShadowCopy) |
||||
b.Append(" /noshadow"); |
||||
if (NoThread) |
||||
b.Append(" /nothread"); |
||||
if (NoLogo) |
||||
b.Append(" /nologo"); |
||||
if (Labels) |
||||
b.Append(" /labels"); |
||||
if (NoDots) |
||||
b.Append(" /nodots"); |
||||
if (XmlOutputFile != null) { |
||||
b.Append(" /xml=\""); |
||||
b.Append(XmlOutputFile); |
||||
b.Append('"'); |
||||
} |
||||
if (Results != null) { |
||||
b.Append(" /results=\""); |
||||
b.Append(Results); |
||||
b.Append('"'); |
||||
} |
||||
string run = null; |
||||
if (NamespaceFilter != null) { |
||||
run = NamespaceFilter; |
||||
} else if (Fixture != null) { |
||||
if (Test != null) { |
||||
run = Fixture + "." + Test; |
||||
} else { |
||||
run = Fixture; |
||||
} |
||||
} else if (Test != null) { |
||||
run = Test; |
||||
} |
||||
if (run != null) { |
||||
b.Append(" /run=\""); |
||||
b.Append(run); |
||||
b.Append('"'); |
||||
} |
||||
return b.ToString(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Checks that the project's PlatformTarget is x86 for the active configuration.
|
||||
/// </summary>
|
||||
bool IsPlatformTarget32Bit(IProject project) |
||||
{ |
||||
MSBuildBasedProject msbuildProject = project as MSBuildBasedProject; |
||||
if (msbuildProject != null) { |
||||
string platformTarget = msbuildProject.GetEvaluatedProperty("PlatformTarget"); |
||||
return String.Equals(platformTarget, "x86", StringComparison.OrdinalIgnoreCase); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
bool ProjectUsesDotnet20Runtime(IProject project) |
||||
{ |
||||
MSBuildBasedProject msbuildProject = project as MSBuildBasedProject; |
||||
if (msbuildProject != null) { |
||||
string targetFrameworkVersion = msbuildProject.GetEvaluatedProperty("TargetFrameworkVersion"); |
||||
return !String.Equals(targetFrameworkVersion, "v4.0", StringComparison.OrdinalIgnoreCase); |
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
@ -1,15 +0,0 @@
@@ -1,15 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class UnitTestBuildOptions : IBuildOptions |
||||
{ |
||||
public bool ShowErrorListAfterBuild { |
||||
get { return BuildOptions.ShowErrorListAfterBuild; } |
||||
} |
||||
} |
||||
} |
||||
@ -1,18 +0,0 @@
@@ -1,18 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using ICSharpCode.SharpDevelop.Project.Commands; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class UnitTestBuildProjectFactory : IBuildProjectFactory |
||||
{ |
||||
public BuildProject CreateBuildProjectBeforeTestRun(IEnumerable<IProject> projects) |
||||
{ |
||||
return new BuildProjectBeforeExecute(new MultipleProjectBuildable(projects)); |
||||
} |
||||
} |
||||
} |
||||
@ -1,19 +0,0 @@
@@ -1,19 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class UnitTestDebuggerService : IUnitTestDebuggerService |
||||
{ |
||||
public bool IsDebuggerLoaded { |
||||
get { return DebuggerService.IsDebuggerLoaded; } |
||||
} |
||||
|
||||
public IDebugger CurrentDebugger { |
||||
get { return DebuggerService.CurrentDebugger; } |
||||
} |
||||
} |
||||
} |
||||
@ -1,27 +0,0 @@
@@ -1,27 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.IO; |
||||
using ICSharpCode.SharpDevelop; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class UnitTestFileService : IUnitTestFileService |
||||
{ |
||||
public void OpenFile(string fileName) |
||||
{ |
||||
FileService.OpenFile(fileName); |
||||
} |
||||
|
||||
public void JumpToFilePosition(string fileName, int line, int column) |
||||
{ |
||||
FileService.JumpToFilePosition(fileName, line, column); |
||||
} |
||||
|
||||
public bool FileExists(string fileName) |
||||
{ |
||||
return File.Exists(fileName); |
||||
} |
||||
} |
||||
} |
||||
@ -1,24 +0,0 @@
@@ -1,24 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.Core.Services; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class UnitTestMessageService : IUnitTestMessageService |
||||
{ |
||||
public bool AskQuestion(string question, string caption) |
||||
{ |
||||
return ServiceManager.Instance.MessageService.AskQuestion(question, caption); |
||||
} |
||||
|
||||
public void ShowFormattedErrorMessage(string format, string item) |
||||
{ |
||||
format = StringParser.Parse(format); |
||||
string message = String.Format(format, item); |
||||
ServiceManager.Instance.MessageService.ShowError(message); |
||||
} |
||||
} |
||||
} |
||||
@ -1,58 +0,0 @@
@@ -1,58 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using ICSharpCode.SharpDevelop.Util; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class UnitTestProcessRunner : IUnitTestProcessRunner |
||||
{ |
||||
ProcessRunner runner; |
||||
|
||||
public event LineReceivedEventHandler OutputLineReceived { |
||||
add { runner.OutputLineReceived += value; } |
||||
remove { runner.OutputLineReceived -= value; } |
||||
} |
||||
|
||||
public event LineReceivedEventHandler ErrorLineReceived { |
||||
add { runner.ErrorLineReceived += value; } |
||||
remove { runner.ErrorLineReceived -= value; } |
||||
} |
||||
|
||||
public event EventHandler ProcessExited { |
||||
add { runner.ProcessExited += value; } |
||||
remove { runner.ProcessExited -= value; } |
||||
} |
||||
|
||||
public UnitTestProcessRunner() |
||||
{ |
||||
runner = new ProcessRunner(); |
||||
} |
||||
|
||||
public bool LogStandardOutputAndError { |
||||
get { return runner.LogStandardOutputAndError; } |
||||
set { runner.LogStandardOutputAndError = value; } |
||||
} |
||||
|
||||
public string WorkingDirectory { |
||||
get { return runner.WorkingDirectory; } |
||||
set { runner.WorkingDirectory = value; } |
||||
} |
||||
|
||||
public Dictionary<string, string> EnvironmentVariables { |
||||
get { return runner.EnvironmentVariables; } |
||||
} |
||||
|
||||
public void Start(string command, string arguments) |
||||
{ |
||||
runner.Start(command, arguments); |
||||
} |
||||
|
||||
public void Kill() |
||||
{ |
||||
runner.Kill(); |
||||
} |
||||
} |
||||
} |
||||
@ -1,15 +0,0 @@
@@ -1,15 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class UnitTestSaveAllFilesCommand : IUnitTestSaveAllFilesCommand |
||||
{ |
||||
public void SaveAllFiles() |
||||
{ |
||||
ICSharpCode.SharpDevelop.Commands.SaveAllFiles.SaveAll(); |
||||
} |
||||
} |
||||
} |
||||
@ -1,27 +0,0 @@
@@ -1,27 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class UnitTestWorkbench : IUnitTestWorkbench |
||||
{ |
||||
public PadDescriptor GetPad(Type type) |
||||
{ |
||||
return WorkbenchSingleton.Workbench.GetPad(type); |
||||
} |
||||
|
||||
public void SafeThreadAsyncCall(Action method) |
||||
{ |
||||
WorkbenchSingleton.SafeThreadAsyncCall(method); |
||||
} |
||||
|
||||
public void SafeThreadAsyncCall<A>(Action<A> method, A arg1) |
||||
{ |
||||
WorkbenchSingleton.SafeThreadAsyncCall(method, arg1); |
||||
} |
||||
} |
||||
} |
||||
@ -1,220 +0,0 @@
@@ -1,220 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.IO; |
||||
using System.Text; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
/// <summary>
|
||||
/// Helper to run the unit testing console application.
|
||||
/// </summary>
|
||||
public class UnitTestApplicationStartHelper |
||||
{ |
||||
/// <summary>
|
||||
/// returns full/path/to/Tools/NUnit
|
||||
/// </summary>
|
||||
public static string UnitTestApplicationDirectory { |
||||
get { |
||||
return Path.Combine(FileUtility.ApplicationRootPath, @"bin\Tools\NUnit"); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// returns full/path/to/Tools/NUnit/nunit-console.exe (or whichever nunit-console exe is right
|
||||
/// for the project - there are different .exes for .NET 4.0 and for x86-only projects.
|
||||
/// </summary>
|
||||
public string UnitTestApplication { |
||||
get { |
||||
string exe = "nunit-console"; |
||||
if (ProjectUsesDotnet20Runtime(project)) { |
||||
exe += "-dotnet2"; |
||||
} |
||||
if (IsPlatformTarget32Bit(project)) { |
||||
exe += "-x86"; |
||||
} |
||||
exe += ".exe"; |
||||
return Path.Combine(UnitTestApplicationDirectory, exe); |
||||
} |
||||
} |
||||
|
||||
public readonly List<string> Assemblies = new List<string>(); |
||||
|
||||
/// <summary>
|
||||
/// Use shadow copy assemblies. Default = true.
|
||||
/// </summary>
|
||||
public bool ShadowCopy = true; |
||||
|
||||
/// <summary>
|
||||
/// Disables the use of a separate thread to run tests on separate thread. Default = false;
|
||||
/// </summary>
|
||||
public bool NoThread = false; |
||||
|
||||
/// <summary>
|
||||
/// Use /nologo directive.
|
||||
/// </summary>
|
||||
public bool NoLogo = false; |
||||
|
||||
/// <summary>
|
||||
/// Use /labels directive.
|
||||
/// </summary>
|
||||
public bool Labels = false; |
||||
|
||||
/// <summary>
|
||||
/// Use /nodots directive.
|
||||
/// </summary>
|
||||
public bool NoDots = false; |
||||
|
||||
/// <summary>
|
||||
/// File to write xml output to. Default = null.
|
||||
/// </summary>
|
||||
public string XmlOutputFile; |
||||
|
||||
/// <summary>
|
||||
/// Fixture to test. Null = test all fixtures.
|
||||
/// </summary>
|
||||
public string Fixture; |
||||
|
||||
/// <summary>
|
||||
/// Test to run. Null = run all tests. Only valid together with the Fixture property.
|
||||
/// </summary>
|
||||
public string Test; |
||||
|
||||
/// <summary>
|
||||
/// File to write test results to.
|
||||
/// </summary>
|
||||
public string Results; |
||||
|
||||
/// <summary>
|
||||
/// The namespace that tests need to be a part of if they are to
|
||||
/// be run.
|
||||
/// </summary>
|
||||
public string NamespaceFilter; |
||||
|
||||
IProject project; |
||||
|
||||
public void Initialize(IProject project, ITypeDefinition fixture, IMethod test) |
||||
{ |
||||
Initialize(project, null, fixture, test); |
||||
} |
||||
|
||||
public void Initialize(IProject project, string namespaceFilter) |
||||
{ |
||||
Initialize(project, namespaceFilter, null, null); |
||||
} |
||||
|
||||
public void Initialize(IProject project, string namespaceFilter, ITypeDefinition fixture, IMethod test) |
||||
{ |
||||
this.project = project; |
||||
Assemblies.Add(project.OutputAssemblyFullPath); |
||||
if (namespaceFilter != null) { |
||||
NamespaceFilter = namespaceFilter; |
||||
} |
||||
if (fixture != null) { |
||||
Fixture = fixture.ReflectionName; |
||||
if (test != null) { |
||||
Test = test.Name; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public IProject Project { |
||||
get { |
||||
return project; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the full command line to run the unit test application.
|
||||
/// This is the combination of the UnitTestApplication and
|
||||
/// the command line arguments.
|
||||
/// </summary>
|
||||
public string GetCommandLine() |
||||
{ |
||||
return String.Concat("\"", UnitTestApplication, "\" ", GetArguments()); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the arguments to use on the command line to run NUnit.
|
||||
/// </summary>
|
||||
public string GetArguments() |
||||
{ |
||||
StringBuilder b = new StringBuilder(); |
||||
foreach (string assembly in Assemblies) { |
||||
if (b.Length > 0) |
||||
b.Append(' '); |
||||
b.Append('"'); |
||||
b.Append(assembly); |
||||
b.Append('"'); |
||||
} |
||||
if (!ShadowCopy) |
||||
b.Append(" /noshadow"); |
||||
if (NoThread) |
||||
b.Append(" /nothread"); |
||||
if (NoLogo) |
||||
b.Append(" /nologo"); |
||||
if (Labels) |
||||
b.Append(" /labels"); |
||||
if (NoDots) |
||||
b.Append(" /nodots"); |
||||
if (XmlOutputFile != null) { |
||||
b.Append(" /xml=\""); |
||||
b.Append(XmlOutputFile); |
||||
b.Append('"'); |
||||
} |
||||
if (Results != null) { |
||||
b.Append(" /results=\""); |
||||
b.Append(Results); |
||||
b.Append('"'); |
||||
} |
||||
string run = null; |
||||
if (NamespaceFilter != null) { |
||||
run = NamespaceFilter; |
||||
} else if (Fixture != null) { |
||||
if (Test != null) { |
||||
run = Fixture + "." + Test; |
||||
} else { |
||||
run = Fixture; |
||||
} |
||||
} else if (Test != null) { |
||||
run = Test; |
||||
} |
||||
if (run != null) { |
||||
b.Append(" /run=\""); |
||||
b.Append(run); |
||||
b.Append('"'); |
||||
} |
||||
return b.ToString(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Checks that the project's PlatformTarget is x86 for the active configuration.
|
||||
/// </summary>
|
||||
bool IsPlatformTarget32Bit(IProject project) |
||||
{ |
||||
MSBuildBasedProject msbuildProject = project as MSBuildBasedProject; |
||||
if (msbuildProject != null) { |
||||
string platformTarget = msbuildProject.GetEvaluatedProperty("PlatformTarget"); |
||||
return String.Equals(platformTarget, "x86", StringComparison.OrdinalIgnoreCase); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
bool ProjectUsesDotnet20Runtime(IProject project) |
||||
{ |
||||
MSBuildBasedProject msbuildProject = project as MSBuildBasedProject; |
||||
if (msbuildProject != null) { |
||||
string targetFrameworkVersion = msbuildProject.GetEvaluatedProperty("TargetFrameworkVersion"); |
||||
return !String.Equals(targetFrameworkVersion, "v4.0", StringComparison.OrdinalIgnoreCase); |
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue