From da238e118a26dba162292ee9baf6a0e0a97cdb91 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Sun, 6 May 2012 14:22:23 +0100 Subject: [PATCH] Add MSTest runner sample addin. --- .../MSTest.SharpDevelop.Tests.csproj | 69 ++++ .../MSTestFrameworkTests.cs | 338 ++++++++++++++++++ .../MSTestResultsTests.cs | 184 ++++++++++ .../Properties/AssemblyInfo.cs | 31 ++ samples/MSTest/MSTest.SharpDevelop.sln | 24 ++ .../MSTest.SharpDevelop.csproj | 101 ++++++ .../MSTest/MSTest.SharpDevelop/MSTest.addin | 30 ++ .../MSTest.SharpDevelop/MSTestApplication.cs | 46 +++ .../MSTestApplicationCommandLine.cs | 37 ++ .../MSTest.SharpDevelop/MSTestDebugger.cs | 120 +++++++ .../MSTest.SharpDevelop/MSTestFramework.cs | 109 ++++++ .../MSTest.SharpDevelop/MSTestOptions.cs | 26 ++ .../MSTestOptionsPanel.xaml | 32 ++ .../MSTestOptionsPanel.xaml.cs | 64 ++++ .../MSTestQualifiedClassName.cs | 31 ++ .../MSTest.SharpDevelop/MSTestResult.cs | 93 +++++ .../MSTest.SharpDevelop/MSTestResults.cs | 91 +++++ .../MSTestResultsFileName.cs | 27 ++ .../MSTest.SharpDevelop/MSTestRunner.cs | 124 +++++++ .../ProjectItemExtensions.cs | 28 ++ .../Properties/AssemblyInfo.cs | 31 ++ 21 files changed, 1636 insertions(+) create mode 100644 samples/MSTest/MSTest.SharpDevelop.Tests/MSTest.SharpDevelop.Tests.csproj create mode 100644 samples/MSTest/MSTest.SharpDevelop.Tests/MSTestFrameworkTests.cs create mode 100644 samples/MSTest/MSTest.SharpDevelop.Tests/MSTestResultsTests.cs create mode 100644 samples/MSTest/MSTest.SharpDevelop.Tests/Properties/AssemblyInfo.cs create mode 100644 samples/MSTest/MSTest.SharpDevelop.sln create mode 100644 samples/MSTest/MSTest.SharpDevelop/MSTest.SharpDevelop.csproj create mode 100644 samples/MSTest/MSTest.SharpDevelop/MSTest.addin create mode 100644 samples/MSTest/MSTest.SharpDevelop/MSTestApplication.cs create mode 100644 samples/MSTest/MSTest.SharpDevelop/MSTestApplicationCommandLine.cs create mode 100644 samples/MSTest/MSTest.SharpDevelop/MSTestDebugger.cs create mode 100644 samples/MSTest/MSTest.SharpDevelop/MSTestFramework.cs create mode 100644 samples/MSTest/MSTest.SharpDevelop/MSTestOptions.cs create mode 100644 samples/MSTest/MSTest.SharpDevelop/MSTestOptionsPanel.xaml create mode 100644 samples/MSTest/MSTest.SharpDevelop/MSTestOptionsPanel.xaml.cs create mode 100644 samples/MSTest/MSTest.SharpDevelop/MSTestQualifiedClassName.cs create mode 100644 samples/MSTest/MSTest.SharpDevelop/MSTestResult.cs create mode 100644 samples/MSTest/MSTest.SharpDevelop/MSTestResults.cs create mode 100644 samples/MSTest/MSTest.SharpDevelop/MSTestResultsFileName.cs create mode 100644 samples/MSTest/MSTest.SharpDevelop/MSTestRunner.cs create mode 100644 samples/MSTest/MSTest.SharpDevelop/ProjectItemExtensions.cs create mode 100644 samples/MSTest/MSTest.SharpDevelop/Properties/AssemblyInfo.cs diff --git a/samples/MSTest/MSTest.SharpDevelop.Tests/MSTest.SharpDevelop.Tests.csproj b/samples/MSTest/MSTest.SharpDevelop.Tests/MSTest.SharpDevelop.Tests.csproj new file mode 100644 index 0000000000..8334f2708a --- /dev/null +++ b/samples/MSTest/MSTest.SharpDevelop.Tests/MSTest.SharpDevelop.Tests.csproj @@ -0,0 +1,69 @@ + + + + {51D56190-67B7-4A49-BA0A-24010460CCC6} + Debug + x86 + Library + MSTest.SharpDevelop.Tests + MSTest.SharpDevelop.Tests + v4.0 + Properties + + + x86 + + + bin\Debug\ + True + Full + False + True + DEBUG;TRACE + + + bin\Release\ + False + None + True + False + TRACE + + + + ..\..\..\bin\ICSharpCode.Core.dll + + + ..\..\..\bin\ICSharpCode.SharpDevelop.dll + + + ..\..\..\bin\ICSharpCode.SharpDevelop.Dom.dll + + + ..\..\..\src\Tools\NUnit\nunit.framework.dll + + + ..\..\..\src\Libraries\RhinoMocks\Rhino.Mocks.dll + + + + 3.5 + + + + ..\..\..\AddIns\Analysis\UnitTesting\UnitTesting.dll + + + + + + + + + + {8DF3A610-47F9-4448-B455-952BD57CB5CC} + MSTest.SharpDevelop + + + + \ No newline at end of file diff --git a/samples/MSTest/MSTest.SharpDevelop.Tests/MSTestFrameworkTests.cs b/samples/MSTest/MSTest.SharpDevelop.Tests/MSTestFrameworkTests.cs new file mode 100644 index 0000000000..be70c9d48c --- /dev/null +++ b/samples/MSTest/MSTest.SharpDevelop.Tests/MSTestFrameworkTests.cs @@ -0,0 +1,338 @@ +// 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.MSTest; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.UnitTesting; +using NUnit.Framework; +using Rhino.Mocks; + +namespace MSTest.SharpDevelop.Tests +{ + [TestFixture] + public class MSTestFrameworkTests + { + MSTestFramework testFramework; + IProject fakeProject; + + [SetUp] + public void Init() + { + testFramework = new MSTestFramework(); + + fakeProject = MockRepository.GenerateStub(); + fakeProject.Stub(p => p.SyncRoot).Return(fakeProject); + } + + void AddReferencesToProject(params string[] referenceNames) + { + List projectItems = referenceNames + .Select(name => new ReferenceProjectItem(fakeProject, name) as ProjectItem) + .ToList(); + + AddItemsToProject(projectItems); + } + + void AddItemsToProject(List projectItems) + { + fakeProject + .Stub(project => project.Items) + .Return(new ReadOnlyCollection(projectItems)); + } + + void AddFileAndReferenceToProject(string fileName, string reference) + { + var projectItems = new List(); + projectItems.Add(new FileProjectItem(fakeProject, ItemType.Compile, fileName)); + projectItems.Add(new ReferenceProjectItem(fakeProject, reference)); + + AddItemsToProject(projectItems); + } + + void NoItemsInProject() + { + AddReferencesToProject(); + } + + IClass CreateClassWithoutAnyAttributes() + { + IClass fakeClass = MockRepository.GenerateStub(); + AddAttributesToClass(fakeClass, new List()); + return fakeClass; + } + + void AddAttributesToClass(IClass fakeClass, List attributes) + { + fakeClass.Stub(c => c.Attributes).Return(attributes); + } + + IClass CreateClassWithAttributes(params string[] attributeNames) + { + IClass fakeClass = MockRepository.GenerateStub(); + + List attributes = CreateAttributes(attributeNames); + + AddAttributesToClass(fakeClass, attributes); + + return fakeClass; + } + + List CreateAttributes(params string[] attributeNames) + { + return attributeNames.Select(name => CreateAttribute(name)).ToList(); + } + + IAttribute CreateAttribute(string name) + { + IReturnType returnType = MockRepository.GenerateStub(); + returnType.Stub(t => t.FullyQualifiedName).Return(name); + + IAttribute attribute = MockRepository.GenerateStub(); + attribute.Stub(a => a.AttributeType).Return(returnType); + return attribute; + } + + void MakeClassAbstract(IClass fakeClass) + { + fakeClass.Stub(c => c.IsAbstract).Return(true); + } + + IMethod CreateMethodWithoutAnyAttributes() + { + IMethod fakeMethod = MockRepository.GenerateStub(); + AddAttributesToMethod(fakeMethod, new List()); + return fakeMethod; + } + + IMethod CreateMethodWithAttributes(params string[] attributeNames) + { + IMethod fakeMethod = MockRepository.GenerateStub(); + List attributes = CreateAttributes(attributeNames); + AddAttributesToMethod(fakeMethod, attributes); + return fakeMethod; + } + + void AddAttributesToMethod(IMethod method, List attributes) + { + method.Stub(m => m.Attributes).Return(attributes); + } + + List GetTestMembersFor(IClass fakeClass) + { + return testFramework.GetTestMembersFor(fakeClass).ToList(); + } + + void AddMethodsToClass(IClass fakeClass, List methods) + { + fakeClass.Stub(c => c.Methods).Return(methods); + } + + [Test] + public void IsTestProject_NullProject_ReturnsFalse() + { + bool result = testFramework.IsTestProject(null); + + Assert.IsFalse(result); + } + + [Test] + public void IsTestProject_ProjectWithMSTestAssemblyReference_ReturnsTrue() + { + AddReferencesToProject("System", "Microsoft.VisualStudio.QualityTools.UnitTestFramework"); + + bool result = testFramework.IsTestProject(fakeProject); + + Assert.IsTrue(result); + } + + [Test] + public void IsTestProject_ProjectWithoutMSTestAssemblyReference_ReturnsFalse() + { + NoItemsInProject(); + bool result = testFramework.IsTestProject(fakeProject); + + Assert.IsFalse(result); + } + + [Test] + public void IsTestProject_ProjectWithMSTestAssemblyReferenceInUpperCase_ReturnsTrue() + { + AddReferencesToProject("MICROSOFT.VISUALSTUDIO.QUALITYTOOLS.UNITTESTFRAMEWORK"); + + bool result = testFramework.IsTestProject(fakeProject); + + Assert.IsTrue(result); + } + + [Test] + public void IsTestProject_ProjectWithMSTestAssemblyReferenceAndFileProjectItem_ReturnsTrue() + { + AddFileAndReferenceToProject("test.cs", "Microsoft.VisualStudio.QualityTools.UnitTestFramework"); + + bool result = testFramework.IsTestProject(fakeProject); + + Assert.IsTrue(result); + } + + [Test] + public void IsTestProject_ProjectWithMSTestAssemblyReferenceUsingFullName_ReturnsTrue() + { + AddReferencesToProject("Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=2.5.3.9345, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77"); + + bool result = testFramework.IsTestProject(fakeProject); + + Assert.IsTrue(result); + } + + [Test] + public void IsTestClass_ClassHasNoAttributes_ReturnsFalse() + { + IClass fakeClass = CreateClassWithoutAnyAttributes(); + + bool result = testFramework.IsTestClass(fakeClass); + + Assert.IsFalse(result); + } + + [Test] + public void IsTestClass_ClassHasTestFixtureAttributeMissingAttributePart_ReturnsTrue() + { + IClass fakeClass = CreateClassWithAttributes("TestClass"); + + bool result = testFramework.IsTestClass(fakeClass); + + Assert.IsTrue(result); + } + + [Test] + public void IsTestClass_ClassHasTestClassAttributeAndIsAbstract_ReturnsFalse() + { + IClass fakeClass = CreateClassWithAttributes("TestClass"); + MakeClassAbstract(fakeClass); + + bool result = testFramework.IsTestClass(fakeClass); + + Assert.IsFalse(result); + } + + [Test] + public void IsTestClass_ClassHasTestClassAttributeIncludingAttributePart_ReturnsTrue() + { + IClass fakeClass = CreateClassWithAttributes("TestClassAttribute"); + + bool result = testFramework.IsTestClass(fakeClass); + + Assert.IsTrue(result); + } + + [Test] + public void IsTestClass_ClassHasFullyQualifiedMSTestClassAttribute_ReturnsTrue() + { + IClass fakeClass = CreateClassWithAttributes("Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute"); + + bool result = testFramework.IsTestClass(fakeClass); + + Assert.IsTrue(result); + } + + [Test] + public void IsTestClass_ClassIsNull_ReturnsFalse() + { + bool result = testFramework.IsTestClass(null); + + Assert.IsFalse(result); + } + + [Test] + public void IsTestMember_MethodHasNoAttributes_ReturnsFalse() + { + IMethod method = CreateMethodWithoutAnyAttributes(); + + bool result = testFramework.IsTestMember(method); + + Assert.IsFalse(result); + } + + [Test] + public void IsTestMember_MethodHasTestMethodAttributeWithoutAttributePart_ReturnsTrue() + { + IMethod method = CreateMethodWithAttributes("TestMethod"); + + bool result = testFramework.IsTestMember(method); + + Assert.IsTrue(result); + } + + [Test] + public void IsTestMember_MethodHasTestMethodAttributeAttribute_ReturnsTrue() + { + IMethod method = CreateMethodWithAttributes("TestMethodAttribute"); + + bool result = testFramework.IsTestMember(method); + + Assert.IsTrue(result); + } + + [Test] + public void IsTestMember_MethodHasFullyQualifiedMSTestTestMethodAttribute_ReturnsTrue() + { + IMethod method = CreateMethodWithAttributes("Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute"); + + bool result = testFramework.IsTestMember(method); + + Assert.IsTrue(result); + } + + [Test] + public void IsTestMember_MethodIsNull_ReturnsFalse() + { + bool result = testFramework.IsTestMember(null); + + Assert.IsFalse(result); + } + + [Test] + public void IsTestMember_MemberNotMethod_ReturnsFalse() + { + IMember member = MockRepository.GenerateStub(); + + bool result = testFramework.IsTestMember(member); + + Assert.IsFalse(result); + } + + [Test] + public void GetTestMembersFor_ClassHasNoMethods_ReturnsFalse() + { + IClass fakeClass = CreateClassWithAttributes("TestClass"); + AddMethodsToClass(fakeClass, new List()); + + List testMembers = GetTestMembersFor(fakeClass); + + Assert.AreEqual(0, testMembers.Count); + } + + [Test] + public void GetTestMembersFor_ClassHasTwoMethodsAndSecondOneIsTestMethod_ReturnsSecondTestMethodOnly() + { + IClass fakeClass = CreateClassWithAttributes("TestClass"); + + var methods = new List(); + methods.Add(CreateMethodWithoutAnyAttributes()); + IMethod testMethod = CreateMethodWithAttributes("TestMethod"); + methods.Add(testMethod); + AddMethodsToClass(fakeClass, methods); + + List testMembers = GetTestMembersFor(fakeClass); + + Assert.AreEqual(1, testMembers.Count); + Assert.AreEqual(testMethod, testMembers[0].Member); + } + } +} diff --git a/samples/MSTest/MSTest.SharpDevelop.Tests/MSTestResultsTests.cs b/samples/MSTest/MSTest.SharpDevelop.Tests/MSTestResultsTests.cs new file mode 100644 index 0000000000..c5304011f6 --- /dev/null +++ b/samples/MSTest/MSTest.SharpDevelop.Tests/MSTestResultsTests.cs @@ -0,0 +1,184 @@ +// 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.Linq; +using System.Xml; +using ICSharpCode.MSTest; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.UnitTesting; +using NUnit.Framework; + +namespace MSTest.SharpDevelop.Tests +{ + [TestFixture] + public class MSTestResultsTests + { + MSTestResults testResults; + + void CreateMSTestResults(string xml) + { + using (var reader = new XmlTextReader(new StringReader(xml))) { + testResults = new MSTestResults(reader); + } + } + + void AssertTestResultsAreEqual(TestResult[] expectedResults) + { + List expectedResultsAsString = ConvertToStrings(expectedResults); + List actualResultsAsString = ConvertToStrings(testResults); + CollectionAssert.AreEqual(expectedResultsAsString, actualResultsAsString); + } + + List ConvertToStrings(IEnumerable results) + { + return results.Select( + result => String.Format( + "Name: {0}, Result: {1}, Message: '{2}', StackTrace: '{3}', StackPosition: {4}", + result.Name, + result.ResultType, + result.Message, + result.StackTrace, + result.StackTraceFilePosition)) + .ToList(); + } + + [Test] + public void Results_OneClassWithTwoPassingTestMethods_ReturnsTwoResults() + { + CreateMSTestResults(oneClassWithTwoPassingTestMethods); + + var expectedResults = new TestResult[] { + new TestResult("FooTest.UnitTest1.TestMethod1") { + ResultType = TestResultType.Success + }, + new TestResult("FooTest.UnitTest1.TestMethod2") { + ResultType = TestResultType.Success + }, + }; + AssertTestResultsAreEqual(expectedResults); + } + + string oneClassWithTwoPassingTestMethods = + +@" + + + These are default test settings for a local test run. + + + + + + + + + + + + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +"; + + [Test] + public void Results_OneTestMethodThrowsException_ReturnsOneErrorResultWithStackTrace() + { + CreateMSTestResults(oneTestMethodThrowsException); + + var expectedResults = new TestResult[] { + new TestResult("FooTest.UnitTest1.TestMethod1") { + ResultType = TestResultType.Failure, + Message = "System.ApplicationException: asdfafds", + StackTrace = " at FooTest.UnitTest1.TestMethod1() in d:\\projects\\FooTest\\UnitTest1.cs:line 21\r\n", + StackTraceFilePosition = new FilePosition(@"d:\projects\FooTest\UnitTest1.cs", 21, 1) + } + }; + AssertTestResultsAreEqual(expectedResults); + } + + string oneTestMethodThrowsException = + +@" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Test method FooTest.UnitTest1.TestMethod1 threw exception: +System.ApplicationException: asdfafds + at FooTest.UnitTest1.TestMethod1() in d:\projects\FooTest\UnitTest1.cs:line 21 + + + + + +"; + } +} diff --git a/samples/MSTest/MSTest.SharpDevelop.Tests/Properties/AssemblyInfo.cs b/samples/MSTest/MSTest.SharpDevelop.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..cdff605abd --- /dev/null +++ b/samples/MSTest/MSTest.SharpDevelop.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,31 @@ +#region Using directives + +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +#endregion + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MSTest.SharpDevelop.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MSTest.SharpDevelop.Tests")] +[assembly: AssemblyCopyright("Copyright 2012")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all the values or you can use the default the Revision and +// Build Numbers by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0")] diff --git a/samples/MSTest/MSTest.SharpDevelop.sln b/samples/MSTest/MSTest.SharpDevelop.sln new file mode 100644 index 0000000000..6166e73ff1 --- /dev/null +++ b/samples/MSTest/MSTest.SharpDevelop.sln @@ -0,0 +1,24 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +# SharpDevelop 4.2.0.8749-Beta 2 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MSTest.SharpDevelop", "MSTest.SharpDevelop\MSTest.SharpDevelop.csproj", "{8DF3A610-47F9-4448-B455-952BD57CB5CC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MSTest.SharpDevelop.Tests", "MSTest.SharpDevelop.Tests\MSTest.SharpDevelop.Tests.csproj", "{51D56190-67B7-4A49-BA0A-24010460CCC6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8DF3A610-47F9-4448-B455-952BD57CB5CC}.Debug|x86.Build.0 = Debug|x86 + {8DF3A610-47F9-4448-B455-952BD57CB5CC}.Debug|x86.ActiveCfg = Debug|x86 + {8DF3A610-47F9-4448-B455-952BD57CB5CC}.Release|x86.Build.0 = Release|x86 + {8DF3A610-47F9-4448-B455-952BD57CB5CC}.Release|x86.ActiveCfg = Release|x86 + {51D56190-67B7-4A49-BA0A-24010460CCC6}.Debug|x86.Build.0 = Debug|x86 + {51D56190-67B7-4A49-BA0A-24010460CCC6}.Debug|x86.ActiveCfg = Debug|x86 + {51D56190-67B7-4A49-BA0A-24010460CCC6}.Release|x86.Build.0 = Release|x86 + {51D56190-67B7-4A49-BA0A-24010460CCC6}.Release|x86.ActiveCfg = Release|x86 + EndGlobalSection +EndGlobal diff --git a/samples/MSTest/MSTest.SharpDevelop/MSTest.SharpDevelop.csproj b/samples/MSTest/MSTest.SharpDevelop/MSTest.SharpDevelop.csproj new file mode 100644 index 0000000000..7cea733274 --- /dev/null +++ b/samples/MSTest/MSTest.SharpDevelop/MSTest.SharpDevelop.csproj @@ -0,0 +1,101 @@ + + + + {8DF3A610-47F9-4448-B455-952BD57CB5CC} + Debug + x86 + Library + ICSharpCode.MSTest + MSTest.SharpDevelop + v4.0 + Properties + ..\..\..\AddIns\Samples\MSTest + False + False + 4 + false + + + x86 + False + Auto + 4194304 + 4096 + + + true + Full + False + True + DEBUG;TRACE + + + False + None + True + False + TRACE + + + + ..\..\..\bin\ICSharpCode.Core.dll + False + + + ..\..\..\bin\ICSharpCode.Core.Presentation.dll + + + ..\..\..\bin\ICSharpCode.SharpDevelop.dll + False + + + ..\..\..\bin\ICSharpCode.SharpDevelop.Dom.dll + False + + + ..\..\..\bin\ICSharpCode.SharpDevelop.Widgets.dll + + + + + + 3.5 + + + 4.0 + + + + ..\..\..\AddIns\Analysis\UnitTesting\UnitTesting.dll + False + + + + + + + + + + + MSTestOptionsPanel.xaml + Code + + + + + + + + + + + + Always + + + + + + + \ No newline at end of file diff --git a/samples/MSTest/MSTest.SharpDevelop/MSTest.addin b/samples/MSTest/MSTest.SharpDevelop/MSTest.addin new file mode 100644 index 0000000000..3049a6c8d0 --- /dev/null +++ b/samples/MSTest/MSTest.SharpDevelop/MSTest.addin @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/samples/MSTest/MSTest.SharpDevelop/MSTestApplication.cs b/samples/MSTest/MSTest.SharpDevelop/MSTestApplication.cs new file mode 100644 index 0000000000..62e3985228 --- /dev/null +++ b/samples/MSTest/MSTest.SharpDevelop/MSTestApplication.cs @@ -0,0 +1,46 @@ +// 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.UnitTesting; + +namespace ICSharpCode.MSTest +{ + public class MSTestApplication + { + SelectedTests selectedTests; + string resultsFileName; + + public MSTestApplication(SelectedTests selectedTests, string resultsFileName) + { + this.selectedTests = selectedTests; + this.resultsFileName = resultsFileName; + GetProcessStartInfo(); + } + + void GetProcessStartInfo() + { + ProcessStartInfo = new ProcessStartInfo(MSTestOptions.MSTestPath, GetCommandLine()); + } + + string GetCommandLine() + { + var commandLine = new MSTestApplicationCommandLine(); + commandLine.AppendQuoted("testcontainer", selectedTests.Project.OutputAssemblyFullPath); + commandLine.AppendQuoted("resultsfile", resultsFileName); + commandLine.Append("detail", "errorstacktrace"); + if (selectedTests.NamespaceFilter != null) { + commandLine.Append("test", selectedTests.NamespaceFilter); + } else if (selectedTests.Member != null) { + commandLine.Append("test", selectedTests.Member.FullyQualifiedName); + } else if (selectedTests.Class != null) { + commandLine.Append("test", selectedTests.Class.FullyQualifiedName); + } + return commandLine.ToString(); + } + + public ProcessStartInfo ProcessStartInfo { get; private set; } + } +} diff --git a/samples/MSTest/MSTest.SharpDevelop/MSTestApplicationCommandLine.cs b/samples/MSTest/MSTest.SharpDevelop/MSTestApplicationCommandLine.cs new file mode 100644 index 0000000000..669d88bba7 --- /dev/null +++ b/samples/MSTest/MSTest.SharpDevelop/MSTestApplicationCommandLine.cs @@ -0,0 +1,37 @@ +// 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.Text; + +namespace ICSharpCode.MSTest +{ + public class MSTestApplicationCommandLine + { + StringBuilder commandLine = new StringBuilder(); + + public MSTestApplicationCommandLine() + { + } + + public void Append(string argument, string value) + { + AppendFormat("/{0}:{1} ", argument, value); + } + + public void AppendQuoted(string argument, string value) + { + AppendFormat("/{0}:\"{1}\" ", argument, value); + } + + void AppendFormat(string format, string argument, string value) + { + commandLine.AppendFormat(format, argument, value); + } + + public override string ToString() + { + return commandLine.ToString(); + } + } +} diff --git a/samples/MSTest/MSTest.SharpDevelop/MSTestDebugger.cs b/samples/MSTest/MSTest.SharpDevelop/MSTestDebugger.cs new file mode 100644 index 0000000000..0d9021a94a --- /dev/null +++ b/samples/MSTest/MSTest.SharpDevelop/MSTestDebugger.cs @@ -0,0 +1,120 @@ +// 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 System.IO; + +using ICSharpCode.SharpDevelop.Debugging; +using ICSharpCode.UnitTesting; + +namespace ICSharpCode.MSTest +{ + public class MSTestDebugger : TestRunnerBase + { + IUnitTestDebuggerService debuggerService; + IUnitTestMessageService messageService; + IDebugger debugger; + string resultsFileName; + + public MSTestDebugger() + : this( + new UnitTestDebuggerService(), + new UnitTestMessageService()) + { + } + + public MSTestDebugger( + IUnitTestDebuggerService debuggerService, + IUnitTestMessageService messageService) + { + this.debuggerService = debuggerService; + this.messageService = messageService; + this.debugger = debuggerService.CurrentDebugger; + } + + public override void Start(SelectedTests selectedTests) + { + ProcessStartInfo startInfo = GetProcessStartInfo(selectedTests); + if (IsDebuggerRunning) { + if (CanStopDebugging()) { + debugger.Stop(); + Start(startInfo); + } + } else { + Start(startInfo); + } + } + + protected override ProcessStartInfo GetProcessStartInfo(SelectedTests selectedTests) + { + resultsFileName = new MSTestResultsFileName(selectedTests).FileName; + var mstestApplication = new MSTestApplication(selectedTests, resultsFileName); + return mstestApplication.ProcessStartInfo; + } + + 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) + { + 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; + + var testResults = new MSTestResults(resultsFileName); + var workbench = new UnitTestWorkbench(); + workbench.SafeThreadAsyncCall(() => UpdateTestResults(testResults)); + } + + void UpdateTestResults(MSTestResults testResults) + { + foreach (TestResult result in testResults) { + OnTestFinished(this, new TestFinishedEventArgs(result)); + } + OnAllTestsFinished(this, new EventArgs()); + } + + public override void Stop() + { + if (debugger.IsDebugging) { + debugger.Stop(); + } + } + + public override void Dispose() + { + Stop(); + try { + File.Delete(resultsFileName); + } catch { } + } + } +} diff --git a/samples/MSTest/MSTest.SharpDevelop/MSTestFramework.cs b/samples/MSTest/MSTest.SharpDevelop/MSTestFramework.cs new file mode 100644 index 0000000000..50e7d4eb59 --- /dev/null +++ b/samples/MSTest/MSTest.SharpDevelop/MSTestFramework.cs @@ -0,0 +1,109 @@ +// 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.Dom; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.UnitTesting; + +namespace ICSharpCode.MSTest +{ + public class MSTestFramework : ITestFramework + { + public bool IsBuildNeededBeforeTestRun { + get { return true; } + } + + public bool IsTestMember(IMember member) + { + var method = member as IMethod; + if (method == null) + return false; + + return IsTestMethod(method); + } + + bool IsTestMethod(IMethod method) + { + foreach (IAttribute attribute in method.Attributes) { + if (IsMSTestMethodAttribute(attribute)) { + return true; + } + } + + return false; + } + + bool IsMSTestMethodAttribute(IAttribute attribute) + { + return IsMSTestMethodAttribute(attribute.AttributeType.FullyQualifiedName); + } + + bool IsMSTestMethodAttribute(string name) + { + return + name == "TestMethod" || + name == "TestMethodAttribute" || + name == "Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute"; + } + + public bool IsTestClass(IClass c) + { + if ((c == null) || (c.IsAbstract)) + return false; + + foreach (IAttribute attribute in c.Attributes) { + if (IsMSTestClassAttribute(attribute)) { + return true; + } + } + + return false; + } + + bool IsMSTestClassAttribute(IAttribute attribute) + { + return IsMSTestClassAttribute(attribute.AttributeType.FullyQualifiedName); + } + + bool IsMSTestClassAttribute(string name) + { + return + name == "TestClass" || + name == "TestClassAttribute" || + name == "Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute"; + } + + public bool IsTestProject(IProject project) + { + if (project == null) + return false; + + foreach (ProjectItem item in project.Items) { + if (item.IsMSTestAssemblyReference()) { + return true; + } + } + return false; + } + + public IEnumerable GetTestMembersFor(IClass c) + { + return c.Methods + .Where(IsTestMethod) + .Select(method => new TestMember(method)); + } + + public ITestRunner CreateTestRunner() + { + return new MSTestRunner(); + } + + public ITestRunner CreateTestDebugger() + { + return new MSTestDebugger(); + } + } +} \ No newline at end of file diff --git a/samples/MSTest/MSTest.SharpDevelop/MSTestOptions.cs b/samples/MSTest/MSTest.SharpDevelop/MSTestOptions.cs new file mode 100644 index 0000000000..f60a73467b --- /dev/null +++ b/samples/MSTest/MSTest.SharpDevelop/MSTestOptions.cs @@ -0,0 +1,26 @@ +// 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.Core; + +namespace ICSharpCode.MSTest +{ + public static class MSTestOptions + { + static Properties properties = PropertyService.Get("MSTestOptions", new Properties()); + + public static string MSTestPath { + get { return properties.Get("MSTestPath", GetDefaultMSTestPath()); } + set { properties.Set("MSTestPath", value); } + } + + static string GetDefaultMSTestPath() + { + return Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), + @"Microsoft Visual Studio 10.0\Common7\IDE\mstest.exe"); + } + } +} diff --git a/samples/MSTest/MSTest.SharpDevelop/MSTestOptionsPanel.xaml b/samples/MSTest/MSTest.SharpDevelop/MSTestOptionsPanel.xaml new file mode 100644 index 0000000000..57da7506a1 --- /dev/null +++ b/samples/MSTest/MSTest.SharpDevelop/MSTestOptionsPanel.xaml @@ -0,0 +1,32 @@ + + + + + + + + + + +