diff --git a/src/AddIns/Analysis/MachineSpecifications/MachineSpecifications.Tests/Src/MSpecTestFrameworkTests.cs b/src/AddIns/Analysis/MachineSpecifications/MachineSpecifications.Tests/Src/MSpecTestFrameworkTests.cs index f817c4cda5..a676936450 100644 --- a/src/AddIns/Analysis/MachineSpecifications/MachineSpecifications.Tests/Src/MSpecTestFrameworkTests.cs +++ b/src/AddIns/Analysis/MachineSpecifications/MachineSpecifications.Tests/Src/MSpecTestFrameworkTests.cs @@ -22,108 +22,158 @@ using Rhino.Mocks; namespace ICSharpCode.MachineSpecifications.Tests { [Subject(typeof(MSpecTestFramework))] - public class When_checking_if_is_a_test_project : Observes - { - static IProject testProject; - static IProject nonTestProject; - - static bool resultForTestProject; + public class When_checking_if_is_a_test_project : Observes + { + static IProject testProject; + static IProject nonTestProject; + + static bool resultForTestProject; static bool resultForNonTestProject; - + const string MSpecAssemblyName = "Machine.Specifications"; - - Establish ctx = () => { + + Establish ctx = () => + { testProject = fake.an(); var mspecReference = MockRepository.GenerateStub(testProject); - mspecReference.setup(x => x.ShortName).Return(MSpecAssemblyName); - testProject.setup(x => x.Items).Return(new ReadOnlyCollection(new[]{mspecReference })); - + mspecReference.setup(x => x.ShortName).Return(MSpecAssemblyName); + testProject.setup(x => x.Items).Return(new ReadOnlyCollection(new[] { mspecReference })); + nonTestProject = fake.an(); var otherReference = MockRepository.GenerateStub(nonTestProject); mspecReference.setup(x => x.ShortName).Return("System.Configuration"); - nonTestProject.setup(x => x.Items).Return(new ReadOnlyCollection(new[]{otherReference })); + nonTestProject.setup(x => x.Items).Return(new ReadOnlyCollection(new[] { otherReference })); }; - - Because of = () => { - resultForTestProject = sut.IsTestProject(testProject); - resultForNonTestProject = sut.IsTestProject(nonTestProject); + + Because of = () => + { + resultForTestProject = sut.IsTestProject(testProject); + resultForNonTestProject = sut.IsTestProject(nonTestProject); }; - It should_return_true_for_project_which_has_reference_to_test_framework = () => - resultForTestProject.ShouldBeTrue(); + It should_return_true_for_project_which_has_reference_to_test_framework = () => + resultForTestProject.ShouldBeTrue(); - It should_return_false_for_project_which_has_no_reference_to_test_framework = () => - resultForNonTestProject.ShouldBeFalse(); + It should_return_false_for_project_which_has_no_reference_to_test_framework = () => + resultForNonTestProject.ShouldBeFalse(); } - [Subject(typeof(MSpecTestFramework))] - public class When_checking_if_is_a_test_class : Observes - { - const string MSpecItTypeName = "Machine.Specifications.It"; - const string MSpecBehavesTypeName = "Machine.Specifications.Behaves_like"; - const string MSpecBehaviorTypeName = "Machine.Specifications.BehaviorsAttribute"; + public abstract class MSpecTestFrameworkFieldsConcern : Observes + { + protected const string MSpecItTypeName = "Machine.Specifications.It"; + protected const string MSpecBehavesTypeName = "Machine.Specifications.Behaves_like"; + protected const string MSpecBehaviorTypeName = "Machine.Specifications.BehaviorsAttribute"; + protected static IClass SetupClass(bool isAbstract, IList fields, IList attributes) + { + var c = fake.an(); + c.setup(x => x.IsAbstract).Return(isAbstract); + c.setup(x => x.Fields).Return(fields); + c.setup(x => x.Attributes).Return(attributes); + return c; + } + + protected static IField SetupField(string returnTypeName) + { + var field = fake.an(); + field.ReturnType = SetupReturnType(returnTypeName); + return field; + } + + protected static IAttribute SetupBehaviorAttribute() + { + var attribute = fake.an(); + attribute.setup(x => x.AttributeType).Return(SetupReturnType(MSpecBehaviorTypeName)); + return attribute; + } + + protected static IReturnType SetupReturnType(string typeName) + { + var returnType = fake.an(); + returnType.Stub(x => x.FullyQualifiedName).Return(typeName); + return returnType; + } + } + + [Subject(typeof(MSpecTestFramework))] + public class When_checking_if_is_a_test_class : MSpecTestFrameworkFieldsConcern + { static IClass classWithoutSpecificationMembers; - static IClass classWithSpecificationMembers; - static IClass classWithBehavior; - static IClass classWithSpecificationMembersAndBehaviorAttribute; - - static bool resultForClassWithBehaviorAttribute; - static bool resultForClassWithSpecifications; - static bool resultForClassWithBehavior; - static bool resultForClassWithoutSpecifications; - - Establish ctx = () => { - classWithoutSpecificationMembers = SetupClass(false, new IField[0], new IAttribute[0]); - classWithSpecificationMembers = SetupClass(false, new IField[]{SetupField(MSpecItTypeName)}, new IAttribute[0]); - classWithBehavior = SetupClass(false, new IField[]{SetupField(MSpecBehavesTypeName)}, new IAttribute[0]); - classWithSpecificationMembersAndBehaviorAttribute = SetupClass(false, new IField[]{SetupField(MSpecItTypeName)}, new IAttribute[]{SetupBehaviorAttribute()}); - }; - - static IClass SetupClass(bool isAbstract, IList fields, IList attributes) { - var c = fake.an(); - c.setup(x => x.IsAbstract).Return(isAbstract); - c.setup(x => x.Fields).Return(fields); - c.setup(x => x.Attributes).Return(attributes); - return c; - } - - static IField SetupField(string returnTypeName) { - var field = fake.an(); - field.ReturnType = SetupReturnType(returnTypeName); - return field; - } - - static IAttribute SetupBehaviorAttribute() { - var attribute = fake.an(); - attribute.setup(x => x.AttributeType).Return(SetupReturnType(MSpecBehaviorTypeName)); - return attribute; - } - - static IReturnType SetupReturnType(string typeName) { - var returnType = fake.an(); - returnType.Stub(x => x.FullyQualifiedName).Return(typeName); - return returnType; - } - - Because of = () => - { - resultForClassWithoutSpecifications = sut.IsTestClass(classWithoutSpecificationMembers); - resultForClassWithSpecifications = sut.IsTestClass(classWithSpecificationMembers); - resultForClassWithBehavior = sut.IsTestClass(classWithBehavior); - resultForClassWithBehaviorAttribute = sut.IsTestClass(classWithSpecificationMembersAndBehaviorAttribute); - }; - - It should_return_false_for_class_without_specification_members = () => - resultForClassWithoutSpecifications.ShouldBeFalse(); - - It should_return_true_for_class_with_specification_members = () => - resultForClassWithSpecifications.ShouldBeTrue(); - - It should_return_true_for_class_with_behavior = () => - resultForClassWithBehavior.ShouldBeTrue(); - - It should_return_false_for_class_with_behavior_attribute = () => - resultForClassWithBehaviorAttribute.ShouldBeFalse(); - } + static IClass classWithSpecificationMembers; + static IClass classWithBehavior; + static IClass classWithSpecificationMembersAndBehaviorAttribute; + + static bool resultForClassWithBehaviorAttribute; + static bool resultForClassWithSpecifications; + static bool resultForClassWithBehavior; + static bool resultForClassWithoutSpecifications; + + Establish ctx = () => + { + classWithoutSpecificationMembers = SetupClass(false, new IField[0], new IAttribute[0]); + classWithSpecificationMembers = SetupClass(false, new IField[] { SetupField(MSpecItTypeName) }, new IAttribute[0]); + classWithBehavior = SetupClass(false, new IField[] { SetupField(MSpecBehavesTypeName) }, new IAttribute[0]); + classWithSpecificationMembersAndBehaviorAttribute = SetupClass(false, new IField[] { SetupField(MSpecItTypeName) }, new IAttribute[] { SetupBehaviorAttribute() }); + }; + + Because of = () => + { + resultForClassWithoutSpecifications = sut.IsTestClass(classWithoutSpecificationMembers); + resultForClassWithSpecifications = sut.IsTestClass(classWithSpecificationMembers); + resultForClassWithBehavior = sut.IsTestClass(classWithBehavior); + resultForClassWithBehaviorAttribute = sut.IsTestClass(classWithSpecificationMembersAndBehaviorAttribute); + }; + + It should_return_false_for_class_without_specification_members = () => + resultForClassWithoutSpecifications.ShouldBeFalse(); + + It should_return_true_for_class_with_specification_members = () => + resultForClassWithSpecifications.ShouldBeTrue(); + + It should_return_true_for_class_with_behavior = () => + resultForClassWithBehavior.ShouldBeTrue(); + + It should_return_false_for_class_with_behavior_attribute = () => + resultForClassWithBehaviorAttribute.ShouldBeFalse(); + } + + public class When_enumerating_test_members : MSpecTestFrameworkFieldsConcern + { + static IClass testClass; + static IField testSpecification; + static IField otherField; + static IField behaviorField; + static IField testSpecificationInBehavior; + static IEnumerable result; + + static IClass behaviorClass; + const string BehaviorClassName = "Test.Behavior"; + + Establish ctx = () => + { + var itReturnType = SetupReturnType(MSpecItTypeName); + + testSpecification = SetupField(MSpecItTypeName); + otherField = SetupField("TestType"); + + var behaviorFieldReturnType = new ConstructedReturnType(SetupReturnType(MSpecBehavesTypeName), new List { SetupReturnType(BehaviorClassName)}); + behaviorField = SetupField(MSpecBehavesTypeName); + + testSpecificationInBehavior = SetupField(MSpecItTypeName); + + testClass = fake.an(); + testClass.setup(x => x.Fields).Return(new List { testSpecification, otherField, behaviorField }); + }; + + Because of = () => result = sut.GetTestMembersFor(testClass); + + It should_contain_field_with_it_return_type = () => + result.ShouldContain(testSpecification); + + It should_not_containt_field_with_arbitrary_return_type = () => + result.ShouldNotContain(otherField); + + It should_containt_it_field_from_behavior = () => + result.ShouldContain(testSpecificationInBehavior); + } } \ No newline at end of file diff --git a/src/AddIns/Analysis/MachineSpecifications/MachineSpecifications.sln b/src/AddIns/Analysis/MachineSpecifications/MachineSpecifications.sln new file mode 100644 index 0000000000..01ebb84929 --- /dev/null +++ b/src/AddIns/Analysis/MachineSpecifications/MachineSpecifications.sln @@ -0,0 +1,74 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MachineSpecifications", "MachineSpecifications\MachineSpecifications.csproj", "{D1DA3B8F-7313-4BDA-8880-461C5F007751}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MachineSpecifications.Tests", "MachineSpecifications.Tests\MachineSpecifications.Tests.csproj", "{172AE35D-2051-4977-AC13-0BF1B76374D5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Core", "..\..\..\Main\Core\Project\ICSharpCode.Core.csproj", "{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.SharpDevelop", "..\..\..\Main\Base\Project\ICSharpCode.SharpDevelop.csproj", "{2748AD25-9C63-4E12-877B-4DCE96FBED54}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.SharpDevelop.Dom", "..\..\..\Main\ICSharpCode.SharpDevelop.Dom\Project\ICSharpCode.SharpDevelop.Dom.csproj", "{924EE450-603D-49C1-A8E5-4AFAA31CE6F3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTesting", "..\UnitTesting\UnitTesting.csproj", "{1F261725-6318-4434-A1B1-6C70CE4CD324}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D1DA3B8F-7313-4BDA-8880-461C5F007751}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D1DA3B8F-7313-4BDA-8880-461C5F007751}.Debug|x86.ActiveCfg = Debug|x86 + {D1DA3B8F-7313-4BDA-8880-461C5F007751}.Debug|x86.Build.0 = Debug|x86 + {D1DA3B8F-7313-4BDA-8880-461C5F007751}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D1DA3B8F-7313-4BDA-8880-461C5F007751}.Release|x86.ActiveCfg = Release|x86 + {D1DA3B8F-7313-4BDA-8880-461C5F007751}.Release|x86.Build.0 = Release|x86 + {172AE35D-2051-4977-AC13-0BF1B76374D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {172AE35D-2051-4977-AC13-0BF1B76374D5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {172AE35D-2051-4977-AC13-0BF1B76374D5}.Debug|x86.ActiveCfg = Debug|Any CPU + {172AE35D-2051-4977-AC13-0BF1B76374D5}.Debug|x86.Build.0 = Debug|Any CPU + {172AE35D-2051-4977-AC13-0BF1B76374D5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {172AE35D-2051-4977-AC13-0BF1B76374D5}.Release|Any CPU.Build.0 = Release|Any CPU + {172AE35D-2051-4977-AC13-0BF1B76374D5}.Release|x86.ActiveCfg = Release|Any CPU + {172AE35D-2051-4977-AC13-0BF1B76374D5}.Release|x86.Build.0 = Release|Any CPU + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Debug|x86.ActiveCfg = Debug|Any CPU + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Debug|x86.Build.0 = Debug|Any CPU + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Release|Any CPU.Build.0 = Release|Any CPU + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Release|x86.ActiveCfg = Release|Any CPU + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Release|x86.Build.0 = Release|Any CPU + {2748AD25-9C63-4E12-877B-4DCE96FBED54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2748AD25-9C63-4E12-877B-4DCE96FBED54}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2748AD25-9C63-4E12-877B-4DCE96FBED54}.Debug|x86.ActiveCfg = Debug|Any CPU + {2748AD25-9C63-4E12-877B-4DCE96FBED54}.Debug|x86.Build.0 = Debug|Any CPU + {2748AD25-9C63-4E12-877B-4DCE96FBED54}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2748AD25-9C63-4E12-877B-4DCE96FBED54}.Release|Any CPU.Build.0 = Release|Any CPU + {2748AD25-9C63-4E12-877B-4DCE96FBED54}.Release|x86.ActiveCfg = Release|Any CPU + {2748AD25-9C63-4E12-877B-4DCE96FBED54}.Release|x86.Build.0 = Release|Any CPU + {924EE450-603D-49C1-A8E5-4AFAA31CE6F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {924EE450-603D-49C1-A8E5-4AFAA31CE6F3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {924EE450-603D-49C1-A8E5-4AFAA31CE6F3}.Debug|x86.ActiveCfg = Debug|Any CPU + {924EE450-603D-49C1-A8E5-4AFAA31CE6F3}.Debug|x86.Build.0 = Debug|Any CPU + {924EE450-603D-49C1-A8E5-4AFAA31CE6F3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {924EE450-603D-49C1-A8E5-4AFAA31CE6F3}.Release|Any CPU.Build.0 = Release|Any CPU + {924EE450-603D-49C1-A8E5-4AFAA31CE6F3}.Release|x86.ActiveCfg = Release|Any CPU + {924EE450-603D-49C1-A8E5-4AFAA31CE6F3}.Release|x86.Build.0 = Release|Any CPU + {1F261725-6318-4434-A1B1-6C70CE4CD324}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1F261725-6318-4434-A1B1-6C70CE4CD324}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1F261725-6318-4434-A1B1-6C70CE4CD324}.Debug|x86.ActiveCfg = Debug|Any CPU + {1F261725-6318-4434-A1B1-6C70CE4CD324}.Debug|x86.Build.0 = Debug|Any CPU + {1F261725-6318-4434-A1B1-6C70CE4CD324}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1F261725-6318-4434-A1B1-6C70CE4CD324}.Release|Any CPU.Build.0 = Release|Any CPU + {1F261725-6318-4434-A1B1-6C70CE4CD324}.Release|x86.ActiveCfg = Release|Any CPU + {1F261725-6318-4434-A1B1-6C70CE4CD324}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/AddIns/Analysis/MachineSpecifications/MachineSpecifications/src/MSpecTestFramework.cs b/src/AddIns/Analysis/MachineSpecifications/MachineSpecifications/src/MSpecTestFramework.cs index b0b4b74f76..34421e935d 100644 --- a/src/AddIns/Analysis/MachineSpecifications/MachineSpecifications/src/MSpecTestFramework.cs +++ b/src/AddIns/Analysis/MachineSpecifications/MachineSpecifications/src/MSpecTestFramework.cs @@ -9,6 +9,7 @@ using System; using System.Collections.Generic; using System.Linq; +using ICSharpCode.Core; using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Project; using ICSharpCode.UnitTesting; @@ -30,9 +31,21 @@ namespace ICSharpCode.MachineSpecifications } public IEnumerable GetTestMembersFor(IClass @class) { - foreach (var field in @class.Fields) - if (IsSpecificationMember(field)) - yield return field; + return GetTestMembers(@class, @class.Fields); + } + + private IEnumerable GetTestMembers(IClass testClass, IList fields) + { + var result = fields.Where(IsSpecificationMember).Cast().ToList(); + foreach (var field in fields) + if (IsBehaviorReference(field)) + { + var behaviorFields = ResolveBehaviorFieldsOf(field); + var behaviorTestMembers = GetTestMembers(testClass, behaviorFields); + var decoratedTestMembers = behaviorTestMembers.Select(f => new BaseTestMethod(testClass, f)).Cast(); + result.AddRange(decoratedTestMembers); + } + return result; } public bool IsTestProject(IProject project) { @@ -56,15 +69,29 @@ namespace ICSharpCode.MachineSpecifications public bool IsBuildNeededBeforeTestRun { get {return true;} } + + private IList ResolveBehaviorFieldsOf(IField field) + { + var fieldReturnType = field.ReturnType.CastToConstructedReturnType(); + if (fieldReturnType == null) return new List(); + if (fieldReturnType.TypeArgumentCount != 1) + LoggingService.Error(string.Format("Expected behavior specification {0} to have one type argument but {1} found.", field.FullyQualifiedName, fieldReturnType.TypeArgumentCount)); + var behaviorClassType = fieldReturnType.TypeArguments.FirstOrDefault(); + + return behaviorClassType != null ? behaviorClassType.GetFields() : new List(); + } private bool HasSpecificationMembers(IClass c) { return !c.IsAbstract && c.Fields.Any(IsSpecificationMember); } + private bool IsBehaviorReference(IField field) { + return MSpecBehavesLikeFQName.Equals(field.ReturnType.FullyQualifiedName); + } + private bool IsSpecificationMember(IField field) { - return MSpecItFQName.Equals(field.ReturnType.FullyQualifiedName) - || MSpecBehavesLikeFQName.Equals(field.ReturnType.FullyQualifiedName); + return MSpecItFQName.Equals(field.ReturnType.FullyQualifiedName); } private bool IsBehavior(IClass c) { diff --git a/src/AddIns/Analysis/UnitTesting/Src/TestClass.cs b/src/AddIns/Analysis/UnitTesting/Src/TestClass.cs index fd0b54dc1b..6ad4fef1cc 100644 --- a/src/AddIns/Analysis/UnitTesting/Src/TestClass.cs +++ b/src/AddIns/Analysis/UnitTesting/Src/TestClass.cs @@ -283,12 +283,12 @@ namespace ICSharpCode.UnitTesting foreach (var member in testFrameworks.GetTestMembersFor(c)) if (!testMembers.Contains(member.Name)) { testMembers.Add(new TestMember(member)); - } + } // Add base class test members. IClass declaringType = c; while (c.BaseClass != null) { - foreach (var method in testFrameworks.GetTestMembersFor(c.BaseClass)) { + foreach (var method in testFrameworks.GetTestMembersFor(c.BaseClass)) { BaseTestMethod baseTestMethod = new BaseTestMethod(declaringType, method); TestMember testMethod = new TestMember(c.BaseClass.Name, baseTestMethod); if (method.IsVirtual) { @@ -299,7 +299,7 @@ namespace ICSharpCode.UnitTesting if (!testMembers.Contains(testMethod.Name)) { testMembers.Add(testMethod); } - } + } } c = c.BaseClass; } diff --git a/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj b/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj index adac04ca1b..de8b830437 100644 --- a/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj +++ b/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj @@ -55,7 +55,9 @@ 3.5 - + + C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0\System.Management.Automation.dll + 4.0