You have been requested to review the proposed merge of lp:~jterrell/nunitv2/action-attributes into lp:nunitv2.
Implements new Action Attributes feature. -- https://code.launchpad.net/~jterrell/nunitv2/action-attributes/+merge/43316 Your team NUnit Core Developers is requested to review the proposed merge of lp:~jterrell/nunitv2/action-attributes into lp:nunitv2.
=== added file 'src/NUnitCore/core/ActionsHelper.cs' --- src/NUnitCore/core/ActionsHelper.cs 1970-01-01 00:00:00 +0000 +++ src/NUnitCore/core/ActionsHelper.cs 2010-12-10 03:36:07 +0000 @@ -0,0 +1,127 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using System.Text; + +namespace NUnit.Core +{ + internal static class ActionsHelper + { + private static Type _ActionInterfaceType = null; + private static Hashtable _ActionTypes = null; + + static ActionsHelper() + { + _ActionInterfaceType = Type.GetType(NUnitFramework.ActionInterface); + _ActionTypes = new Hashtable(); + + _ActionTypes.Add(ActionLevel.Suite, Type.GetType(NUnitFramework.SuiteActionInterface)); + _ActionTypes.Add(ActionLevel.Test, Type.GetType(NUnitFramework.TestActionInterface)); + } + + public static object[] GetActionsFromAttributes(ICustomAttributeProvider attributeProvider) + { + ArrayList resultList = new ArrayList(); + + object[] attributes = attributeProvider.GetCustomAttributes(true); + + foreach (Attribute attribute in attributes) + { + if (_ActionInterfaceType.IsAssignableFrom(attribute.GetType())) + resultList.Add(attribute); + } + + object[] results = new object[resultList.Count]; + resultList.CopyTo(results); + + return results; + } + + public static void ExecuteActions(ActionLevel level, ActionPhase phase, IEnumerable actions, object fixture, MethodInfo method) + { + if (actions == null) + throw new ArgumentNullException("actions"); + + Type actionType = GetActionType(level); + MethodInfo actionMethod = GetActionMethod(actionType, level, phase); + + object[] filteredActions = GetFilteredAndSortedActions(actions, phase, actionType); + + + + foreach (object action in filteredActions) + { + if (action == null) + continue; + + if(level == ActionLevel.Suite) + Reflect.InvokeMethod(actionMethod, action, fixture); + else + Reflect.InvokeMethod(actionMethod, action, fixture, method); + } + } + + private static object[] GetFilteredAndSortedActions(IEnumerable actions, ActionPhase phase, Type actionType) + { + ArrayList filteredActions = new ArrayList(); + foreach(object actionItem in actions) + { + if(actionItem == null) + continue; + + if(actionItem is IEnumerable) + { + foreach(object nestedItem in ((IEnumerable)actionItem)) + { + if(nestedItem == null) + continue; + + if (actionType.IsAssignableFrom(nestedItem.GetType()) && filteredActions.Contains(nestedItem) != true) + filteredActions.Add(nestedItem); + } + } + else if(actionType.IsAssignableFrom(actionItem.GetType()) && filteredActions.Contains(actionItem) != true) + filteredActions.Add(actionItem); + } + + if(phase == ActionPhase.After) + filteredActions.Reverse(); + + return filteredActions.ToArray(); + } + + private static Type GetActionType(ActionLevel level) + { + return (Type) _ActionTypes[level]; + } + + private static MethodInfo GetActionMethod(Type actionType, ActionLevel level, ActionPhase phase) + { + if (phase == ActionPhase.Before) + { + if (level == ActionLevel.Suite) + return Reflect.GetNamedMethod(actionType, "BeforeSuite"); + + return Reflect.GetNamedMethod(actionType, "BeforeTest"); + } + + if (level == ActionLevel.Suite) + return Reflect.GetNamedMethod(actionType, "AfterSuite"); + + return Reflect.GetNamedMethod(actionType, "AfterTest"); + } + } + + internal enum ActionLevel + { + Suite, + Test + } + + internal enum ActionPhase + { + Before, + After + } +} === modified file 'src/NUnitCore/core/Builders/TestAssemblyBuilder.cs' --- src/NUnitCore/core/Builders/TestAssemblyBuilder.cs 2010-08-09 02:30:40 +0000 +++ src/NUnitCore/core/Builders/TestAssemblyBuilder.cs 2010-12-10 03:36:07 +0000 @@ -86,12 +86,12 @@ // a type, we handle it specially Type testType = assembly.GetType(testName); if (testType != null) - return Build(assemblyName, testType, autoSuites); + return Build(assembly, assemblyName, testType, autoSuites); // Assume that testName is a namespace and get all fixtures in it IList fixtures = GetFixtures(assembly, testName); - if (fixtures.Count > 0) - return BuildTestAssembly(assemblyName, fixtures, autoSuites); + if (fixtures.Count > 0) + return BuildTestAssembly(this.assembly, assemblyName, fixtures, autoSuites); return null; } @@ -107,11 +107,11 @@ if (this.assembly == null) return null; IList fixtures = GetFixtures(assembly, null); - return BuildTestAssembly(assemblyName, fixtures, autoSuites); + return BuildTestAssembly(this.assembly, assemblyName, fixtures, autoSuites); } } - private Test Build( string assemblyName, Type testType, bool autoSuites ) + private Test Build( Assembly assembly, string assemblyName, Type testType, bool autoSuites ) { // TODO: This is the only situation in which we currently // recognize and load legacy suites. We need to determine @@ -119,14 +119,14 @@ if ( legacySuiteBuilder.CanBuildFrom( testType ) ) return legacySuiteBuilder.BuildFrom( testType ); else if ( TestFixtureBuilder.CanBuildFrom( testType ) ) - return BuildTestAssembly( assemblyName, + return BuildTestAssembly( assembly, assemblyName, new Test[] { TestFixtureBuilder.BuildFrom( testType ) }, autoSuites ); return null; } - private TestSuite BuildTestAssembly( string assemblyName, IList fixtures, bool autoSuites ) + private TestSuite BuildTestAssembly( Assembly assembly, string assemblyName, IList fixtures, bool autoSuites ) { - TestSuite testAssembly = new TestAssembly( assemblyName ); + TestSuite testAssembly = new TestAssembly( assembly, assemblyName ); if ( autoSuites ) { === modified file 'src/NUnitCore/core/NUnitFramework.cs' --- src/NUnitCore/core/NUnitFramework.cs 2010-11-04 18:12:55 +0000 +++ src/NUnitCore/core/NUnitFramework.cs 2010-12-10 03:36:07 +0000 @@ -23,8 +23,8 @@ #region Constants #region Attribute Names - // NOTE: Attributes used in switch statements must be const - + // NOTE: Attributes used in switch statements must be const + // Attributes that apply to Assemblies, Classes and Methods public const string IgnoreAttribute = "NUnit.Framework.IgnoreAttribute"; public const string PlatformAttribute = "NUnit.Framework.PlatformAttribute"; @@ -54,7 +54,12 @@ public static readonly string SuiteAttribute = "NUnit.Framework.SuiteAttribute"; #endregion - #region Other Framework Types + #region Other Framework Types + + public static readonly string SuiteActionInterface = "NUnit.Framework.ISuiteAction, NUnit.Framework"; + public static readonly string TestActionInterface = "NUnit.Framework.ITestAction, NUnit.Framework"; + public static readonly string ActionInterface = "NUnit.Framework.IAction, NUnit.Framework"; + public static readonly string AssertException = "NUnit.Framework.AssertionException"; public static readonly string IgnoreException = "NUnit.Framework.IgnoreException"; public static readonly string InconclusiveException = "NUnit.Framework.InconclusiveException"; === modified file 'src/NUnitCore/core/NUnitTestFixture.cs' --- src/NUnitCore/core/NUnitTestFixture.cs 2009-04-17 07:12:10 +0000 +++ src/NUnitCore/core/NUnitTestFixture.cs 2010-12-10 03:36:07 +0000 @@ -4,8 +4,9 @@ // copyright ownership at http://nunit.org. // **************************************************************** -using System; -using System.Reflection; +using System; +using System.Reflection; +using System.Collections; namespace NUnit.Core { @@ -27,7 +28,19 @@ this.setUpMethods = Reflect.GetMethodsWithAttribute(this.FixtureType, NUnitFramework.SetUpAttribute, true); this.tearDownMethods = - Reflect.GetMethodsWithAttribute(this.FixtureType, NUnitFramework.TearDownAttribute, true); + Reflect.GetMethodsWithAttribute(this.FixtureType, NUnitFramework.TearDownAttribute, true); + + ArrayList collectedActions = new ArrayList(); + + collectedActions.AddRange(ActionsHelper.GetActionsFromAttributes(fixtureType)); + + Type[] fixtureInterfaces = this.FixtureType.GetInterfaces(); + + foreach (Type fixtureInterface in fixtureInterfaces) + collectedActions.AddRange(ActionsHelper.GetActionsFromAttributes(fixtureInterface)); + + this.actions = new Attribute[collectedActions.Count]; + collectedActions.CopyTo(this.actions); } protected override void DoOneTimeSetUp(TestResult suiteResult) === modified file 'src/NUnitCore/core/ParameterizedTestMethodSuite.cs' --- src/NUnitCore/core/ParameterizedTestMethodSuite.cs 2010-09-21 19:07:23 +0000 +++ src/NUnitCore/core/ParameterizedTestMethodSuite.cs 2010-12-10 03:36:07 +0000 @@ -2,7 +2,8 @@ // Copyright 2008, Charlie Poole // This is free software licensed under the NUnit license. You may // obtain a copy of the license at http://nunit.org. -// **************************************************************** +// **************************************************************** +using System.Collections; using System.Reflection; using System.Text; @@ -14,7 +15,8 @@ /// </summary> public class ParameterizedMethodSuite : TestSuite { - private bool isTheory; + private bool isTheory; + private MethodInfo method; /// <summary> /// Construct from a MethodInfo @@ -24,7 +26,8 @@ : base(method.ReflectedType.FullName, method.Name) { this.maintainTestOrder = true; - this.isTheory = Reflect.HasAttribute(method, NUnitFramework.TheoryAttribute, true); + this.isTheory = Reflect.HasAttribute(method, NUnitFramework.TheoryAttribute, true); + this.method = method; } /// <summary> @@ -56,9 +59,11 @@ if (suite != null) { this.setUpMethods = suite.GetSetUpMethods(); - this.tearDownMethods = suite.GetTearDownMethods(); + this.tearDownMethods = suite.GetTearDownMethods(); } - } + } + + this.actions = ActionsHelper.GetActionsFromAttributes(this.method); // DYNAMIC: Get the parameters, and add the methods here. @@ -74,7 +79,8 @@ this.Fixture = null; this.setUpMethods = null; - this.tearDownMethods = null; + this.tearDownMethods = null; + this.actions = null; return result; } @@ -95,6 +101,6 @@ /// <param name="suiteResult"></param> protected override void DoOneTimeTearDown(TestResult suiteResult) { - } + } } } === modified file 'src/NUnitCore/core/SetUpFixture.cs' --- src/NUnitCore/core/SetUpFixture.cs 2010-01-31 21:39:24 +0000 +++ src/NUnitCore/core/SetUpFixture.cs 2010-12-10 03:36:07 +0000 @@ -27,7 +27,9 @@ this.TestName.Name = this.TestName.Name.Substring(index + 1); this.fixtureSetUpMethods = Reflect.GetMethodsWithAttribute( type, NUnitFramework.SetUpAttribute, true ); - this.fixtureTearDownMethods = Reflect.GetMethodsWithAttribute( type, NUnitFramework.TearDownAttribute, true ); + this.fixtureTearDownMethods = Reflect.GetMethodsWithAttribute( type, NUnitFramework.TearDownAttribute, true ); + + this.actions = ActionsHelper.GetActionsFromAttributes(type); } #endregion === modified file 'src/NUnitCore/core/TestAssembly.cs' --- src/NUnitCore/core/TestAssembly.cs 2010-01-31 21:39:24 +0000 +++ src/NUnitCore/core/TestAssembly.cs 2010-12-10 03:36:07 +0000 @@ -4,8 +4,9 @@ // copyright ownership at http://nunit.org. // **************************************************************** -using System; - +using System; +using System.Reflection; + namespace NUnit.Core { /// <summary> @@ -18,7 +19,10 @@ /// Initializes a new instance of the <see cref="TestAssembly"/> class. /// </summary> /// <param name="path">The path.</param> - public TestAssembly(string path) : base(path) { } + public TestAssembly(Assembly assembly, string path) : base(path) + { + this.actions = ActionsHelper.GetActionsFromAttributes(assembly); + } /// <summary> /// Gets the type of the test. === modified file 'src/NUnitCore/core/TestMethod.cs' --- src/NUnitCore/core/TestMethod.cs 2010-10-10 02:04:39 +0000 +++ src/NUnitCore/core/TestMethod.cs 2010-12-10 03:36:07 +0000 @@ -2,12 +2,11 @@ // This is free software licensed under the NUnit license. You // may obtain a copy of the license as well as information regarding // copyright ownership at http://nunit.org. -// **************************************************************** - +// **************************************************************** namespace NUnit.Core { using System; - using System.Collections; + using System.Collections; using System.Runtime.Remoting.Messaging; using System.Threading; using System.Text; @@ -42,7 +41,17 @@ /// <summary> /// The teardown method /// </summary> - protected MethodInfo[] tearDownMethods; + protected MethodInfo[] tearDownMethods; + + /// <summary> + /// The actions + /// </summary> + protected object[] actions; + + /// <summary> + /// The parent suite's actions + /// </summary> + protected object[] suiteActions; /// <summary> /// The ExpectedExceptionProcessor for this test, if any @@ -210,22 +219,25 @@ ContextDictionary context = Context; context._ec = TestExecutionContext.CurrentContext; - CallContext.SetData("NUnit.Framework.TestContext", context); - - if (this.Parent != null) - { - this.Fixture = this.Parent.Fixture; - TestSuite suite = this.Parent as TestSuite; - if (suite != null) - { - this.setUpMethods = suite.GetSetUpMethods(); - this.tearDownMethods = suite.GetTearDownMethods(); - } - } - - try - { - // Temporary... to allow for tests that directly execute a test case + CallContext.SetData("NUnit.Framework.TestContext", context); + + if (this.Parent != null) + { + this.Fixture = this.Parent.Fixture; + TestSuite suite = this.Parent as TestSuite; + if (suite != null) + { + this.setUpMethods = suite.GetSetUpMethods(); + this.tearDownMethods = suite.GetTearDownMethods(); + this.suiteActions = suite.GetTestActions(); + } + } + + try + { + this.actions = ActionsHelper.GetActionsFromAttributes(method); + + // Temporary... to allow for tests that directly execute a test case); if (Fixture == null && !method.IsStatic) Fixture = Reflect.Construct(this.FixtureType); @@ -300,9 +312,10 @@ TestResult testResult = new TestResult(this); TestExecutionContext.CurrentContext.CurrentResult = testResult; - try - { + try + { RunSetUp(); + RunBeforeActions(); RunTestCase( testResult ); } @@ -317,7 +330,8 @@ } finally { - RunTearDown( testResult ); + RunAfterActions(testResult); + RunTearDown( testResult ); DateTime stop = DateTime.Now; TimeSpan span = stop.Subtract(start); @@ -354,7 +368,29 @@ #region Invoke Methods by Reflection, Recording Errors - private void RunSetUp() + private void RunBeforeActions() + { + object[][] targetActions = new object[][] {this.suiteActions, this.actions}; + ActionsHelper.ExecuteActions(ActionLevel.Test, ActionPhase.Before, targetActions, this.Fixture, this.Method); + } + + private void RunAfterActions(TestResult testResult) + { + try + { + object[][] targetActions = new object[][] { this.suiteActions, this.actions }; + ActionsHelper.ExecuteActions(ActionLevel.Test, ActionPhase.After, targetActions, this.Fixture, this.Method); + } + catch(Exception ex) + { + if (ex is NUnitException) + ex = ex.InnerException; + // TODO: What about ignore exceptions in teardown? + testResult.Error(ex, FailureSite.TearDown); + } + } + + private void RunSetUp() { if (setUpMethods != null) foreach( MethodInfo setUpMethod in setUpMethods ) === modified file 'src/NUnitCore/core/TestSuite.cs' --- src/NUnitCore/core/TestSuite.cs 2010-09-19 22:47:12 +0000 +++ src/NUnitCore/core/TestSuite.cs 2010-12-10 03:36:07 +0000 @@ -46,7 +46,12 @@ /// <summary> /// The teardown methods for this suite /// </summary> - protected MethodInfo[] tearDownMethods; + protected MethodInfo[] tearDownMethods; + + /// <summary> + /// The actions for this suite + /// </summary> + protected object[] actions; /// <summary> /// Set to true to suppress sorting this suite's contents @@ -187,6 +192,24 @@ { return tearDownMethods; } + + internal virtual object[] GetTestActions() + { + ArrayList allActions = new ArrayList(); + + if (this.Parent != null && this.Parent is TestSuite) + { + object[] parentActions = ((TestSuite)this.Parent).GetTestActions(); + + if (parentActions != null) + allActions.AddRange(parentActions); + } + + if (this.actions != null) + allActions.AddRange(this.actions); + + return allActions.ToArray(); + } #endregion #region Test Overrides @@ -268,7 +291,8 @@ { TestResult suiteResult = new TestResult(this); - DoOneTimeSetUp(suiteResult); + DoOneTimeSetUp(suiteResult); + DoOneTimeBeforeTestSuiteActions(suiteResult); if (this.Properties["_SETCULTURE"] != null) TestExecutionContext.CurrentContext.CurrentCulture = @@ -292,8 +316,9 @@ { RunAllTests(suiteResult, listener, filter); } - finally - { + finally + { + DoOneTimeAfterTestSuiteActions(suiteResult); DoOneTimeTearDown(suiteResult); } break; @@ -342,6 +367,36 @@ } } + protected virtual void DoOneTimeBeforeTestSuiteActions(TestResult suiteResult) + { + try + { + if (this.actions != null) + ActionsHelper.ExecuteActions(ActionLevel.Suite, ActionPhase.Before, this.actions, this.Fixture, null); + + TestExecutionContext.CurrentContext.Update(); + } + catch (Exception ex) + { + if (ex is NUnitException || ex is System.Reflection.TargetInvocationException) + ex = ex.InnerException; + + if (ex is InvalidTestFixtureException) + suiteResult.Invalid(ex.Message); + else if (IsIgnoreException(ex)) + { + this.RunState = RunState.Ignored; + suiteResult.Ignore(ex.Message); + suiteResult.StackTrace = ex.StackTrace; + this.IgnoreReason = ex.Message; + } + else if (IsAssertException(ex)) + suiteResult.Failure(ex.Message, ex.StackTrace, FailureSite.SetUp); + else + suiteResult.Error(ex, FailureSite.SetUp); + } + } + protected virtual void CreateUserFixture() { if (arguments != null && arguments.Length > 0) @@ -387,6 +442,26 @@ } } + protected virtual void DoOneTimeAfterTestSuiteActions(TestResult suiteResult) + { + try + { + if (this.actions != null) + ActionsHelper.ExecuteActions(ActionLevel.Suite, ActionPhase.After, this.actions, this.Fixture, null); + } + catch (Exception ex) + { + // Error in TestFixtureTearDown or Dispose causes the + // suite to be marked as a failure, even if + // all the contained tests passed. + NUnitException nex = ex as NUnitException; + if (nex != null) + ex = nex.InnerException; + + suiteResult.Failure(ex.Message, ex.StackTrace, FailureSite.TearDown); + } + } + protected virtual bool IsAssertException(Exception ex) { return ex.GetType().FullName == NUnitFramework.AssertException; @@ -422,9 +497,9 @@ { test.RunState = this.RunState; test.IgnoreReason = this.IgnoreReason; - } - - TestResult result = test.Run(listener, filter); + } + + TestResult result = test.Run(listener, filter); log.Debug("Test result = " + result.ResultState); === modified file 'src/NUnitCore/core/nunit.core.build' --- src/NUnitCore/core/nunit.core.build 2010-12-09 05:10:05 +0000 +++ src/NUnitCore/core/nunit.core.build 2010-12-10 03:36:07 +0000 @@ -3,6 +3,7 @@ <patternset id="source-files"> <include name="AbstractTestCaseDecoration.cs"/> + <include name="ActionsHelper.cs" /> <include name="AssemblyInfo.cs"/> <include name="AssemblyHelper.cs"/> <include name="AssemblyReader.cs"/> === modified file 'src/NUnitCore/core/nunit.core.dll.csproj' --- src/NUnitCore/core/nunit.core.dll.csproj 2010-11-07 15:49:05 +0000 +++ src/NUnitCore/core/nunit.core.dll.csproj 2010-12-10 03:36:07 +0000 @@ -1,8 +1,8 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5"> <PropertyGroup> <ProjectType>Local</ProjectType> - <ProductVersion>9.0.21022</ProductVersion> + <ProductVersion>9.0.30729</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{EBD43A7F-AFCA-4281-BB53-5CDD91F966A3}</ProjectGuid> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> @@ -117,6 +117,7 @@ <Compile Include="AssemblyInfo.cs" /> <Compile Include="AssemblyReader.cs" /> <Compile Include="AssemblyResolver.cs" /> + <Compile Include="ActionsHelper.cs" /> <Compile Include="Builders\CombinatorialStrategy.cs" /> <Compile Include="Builders\CombinatorialTestCaseProvider.cs" /> <Compile Include="Builders\CombiningStrategy.cs" /> === added file 'src/NUnitCore/tests/ActionAttributeTests.cs' --- src/NUnitCore/tests/ActionAttributeTests.cs 1970-01-01 00:00:00 +0000 +++ src/NUnitCore/tests/ActionAttributeTests.cs 2010-12-10 03:36:07 +0000 @@ -0,0 +1,209 @@ +using System; +using System.Collections; +using System.Collections.Specialized; +using NUnit.Framework; +using NUnit.TestData.ActionAttributeTests; + +namespace NUnit.Core.Tests +{ + [TestFixture] + public class ActionAttributeTests + { + private class ActionAttributeFixtureFilter : TestFilter + { + public override bool Match(ITest test) + { + return test.TestName.FullName.StartsWith(typeof(ActionAttributeFixture).FullName); + } + } + + private TestResult _result = null; + private readonly string[] _definitionSites = new string[] + { + "Assembly", + "SetUpFixture", + "Fixture", + "Interface", + "Method" + }; + + [TestFixtureSetUp] + public void Setup() + { + ActionAttributeFixture.Results = new StringCollection(); + + TestSuiteBuilder builder = new TestSuiteBuilder(); + TestPackage package = new TestPackage(AssemblyHelper.GetAssemblyPath(typeof(ActionAttributeFixture))); + package.TestName = typeof(ActionAttributeFixture).Namespace; + + Test suite = builder.Build(package); + _result = suite.Run(new NullListener(), new ActionAttributeFixtureFilter()); + } + + [Test] + public void TestsRunsSuccessfully() + { + Assert.IsTrue(_result.IsSuccess, "Test run was not successful."); + Assert.Contains("SomeTest-Case1", ActionAttributeFixture.Results, "Test Case 1 was not run."); + Assert.Contains("SomeTest-Case2", ActionAttributeFixture.Results, "Test Case 2 was not run."); + Assert.Contains("SomeOtherTest", ActionAttributeFixture.Results, "SomeOtherTest was not run."); + + foreach(string message in ActionAttributeFixture.Results) + Console.WriteLine(message); + } + + [Test] + public void FirstFourDefinitionSites_BeforeSuite_ExecuteFirst_InOrder() + { + for(int i = 0; i < 4; i++) + { + string prefix = string.Format("{0}.BeforeSuite-", _definitionSites[i]); + + Assert.IsTrue( + ActionAttributeFixture.Results[i].StartsWith(prefix), + string.Format("Did not find prefix '{0}' at index {1}", prefix, i)); + } + } + + + [Test] + public void FirstFourDefinitionSites_AfterSuite_ExecuteLast_InOrder() + { + int lastIndex = ActionAttributeFixture.Results.Count - 1; + for (int i = lastIndex; i > lastIndex - 4; i--) + { + string prefix = string.Format("{0}.AfterSuite-", _definitionSites[lastIndex - i]); + + Assert.IsTrue( + ActionAttributeFixture.Results[i].StartsWith(prefix), + string.Format("Did not find prefix '{0}' at index {1}", prefix, i)); + } + } + + [Test] + public void FirstFourDefinitionSites_BeforeTest_ExecuteInOrder_ForSomeOtherTest() + { + int startIndex = ActionAttributeFixture.Results.IndexOf("SomeOtherTest") - 4; + for (int i = startIndex; i < startIndex; i++) + { + string prefix = string.Format("{0}.BeforeTest-", _definitionSites[i - startIndex]); + + Assert.IsTrue( + ActionAttributeFixture.Results[i].StartsWith(prefix), + string.Format("Did not find prefix '{0}' at index {1}", prefix, i)); + } + } + + [Test] + public void FirstFourDefinitionSites_AfterTest_ExecuteInOrder_ForSomeOtherTest() + { + int startIndex = ActionAttributeFixture.Results.IndexOf("SomeOtherTest"); + for (int i = 1; i <= 4; i++) + { + string prefix = string.Format("{0}.AfterTest-", _definitionSites[4 - i]); + + Assert.IsTrue( + ActionAttributeFixture.Results[startIndex + i].StartsWith(prefix), + string.Format("Did not find prefix '{0}' at index {1}", prefix, i)); + } + } + + [Test] + public void AllDefinitionSites_BeforeTest_ExecuteInOrder_ForSomeTestCase1() + { + int startIndex = ActionAttributeFixture.Results.IndexOf("SomeTest-Case1") - 5; + for (int i = startIndex; i < startIndex; i++) + { + string prefix = string.Format("{0}.BeforeTest-", _definitionSites[i - startIndex]); + + Assert.IsTrue( + ActionAttributeFixture.Results[i].StartsWith(prefix), + string.Format("Did not find prefix '{0}' at index {1}", prefix, i)); + } + } + + [Test] + public void AllDefinitionSites_AfterTest_ExecuteInOrder_ForSomeTestCase1() + { + int startIndex = ActionAttributeFixture.Results.IndexOf("SomeTest-Case1"); + for (int i = 1; i <= 5; i++) + { + string prefix = string.Format("{0}.AfterTest-", _definitionSites[5 - i]); + + Assert.IsTrue( + ActionAttributeFixture.Results[startIndex + i].StartsWith(prefix), + string.Format("Did not find prefix '{0}' at index {1}", prefix, i)); + } + } + + [Test] + public void AllDefinitionSites_BeforeTest_ExecuteInOrder_ForSomeTestCase2() + { + int startIndex = ActionAttributeFixture.Results.IndexOf("SomeTest-Case2") - 5; + for (int i = startIndex; i < startIndex; i++) + { + string prefix = string.Format("{0}.BeforeTest-", _definitionSites[i - startIndex]); + + Assert.IsTrue( + ActionAttributeFixture.Results[i].StartsWith(prefix), + string.Format("Did not find prefix '{0}' at index {1}", prefix, i)); + } + } + + [Test] + public void AllDefinitionSites_AfterTest_ExecuteInOrder_ForSomeTestCase2() + { + int startIndex = ActionAttributeFixture.Results.IndexOf("SomeTest-Case2"); + for (int i = 1; i <= 5; i++) + { + string prefix = string.Format("{0}.AfterTest-", _definitionSites[5 - i]); + + Assert.IsTrue( + ActionAttributeFixture.Results[startIndex + i].StartsWith(prefix), + string.Format("Did not find prefix '{0}' at index {1}", prefix, i)); + } + } + + [Test] + public void MethodDefinedSite_BeforeSuite_BeforeSomeTestCase1() + { + int testCase = ActionAttributeFixture.Results.IndexOf("SomeTest-Case1"); + Assert.IsTrue(testCase > ActionAttributeFixture.Results.IndexOf("Method.BeforeSuite-ActionAttributeFixture")); + } + + [Test] + public void MethodDefinedSite_AfterSuite_BeforeSomeTestCase2() + { + int testCase = ActionAttributeFixture.Results.IndexOf("SomeTest-Case2"); + Assert.IsTrue(testCase < ActionAttributeFixture.Results.IndexOf("Method.AfterSuite-ActionAttributeFixture")); + } + + [Test] + public void AllActions_BeforeAndAfterTest_HasAccessToFixture() + { + foreach(string message in ActionAttributeFixture.Results) + { + if (message.Contains("BeforeTest") || message.Contains("AfterTest")) + Assert.IsTrue(message.Contains(typeof(ActionAttributeFixture).Name), string.Format("'{0}' shows action does not have access to fixture.", message)); + } + } + + [Test] + public void AllActions_BeforeAndAfterTest_HasAccessToMethodInfo() + { + StringCollection validEndSegments = new StringCollection(); + validEndSegments.AddRange(new string[] {"SomeOtherTest", "SomeTest"}); + + foreach (string message in ActionAttributeFixture.Results) + { + if (message.Contains("BeforeTest") || message.Contains("AfterTest")) + { + string endSegment = message.Substring(message.LastIndexOf('-') + 1); + + Assert.IsTrue(validEndSegments.Contains(endSegment), + string.Format("'{0}' shows action does not have access to method info.", message)); + } + } + } + } +} === modified file 'src/NUnitCore/tests/nunit.core.tests.csproj' --- src/NUnitCore/tests/nunit.core.tests.csproj 2010-12-09 05:10:05 +0000 +++ src/NUnitCore/tests/nunit.core.tests.csproj 2010-12-10 03:36:07 +0000 @@ -1,8 +1,8 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5"> <PropertyGroup> <ProjectType>Local</ProjectType> - <ProductVersion>9.0.21022</ProductVersion> + <ProductVersion>9.0.30729</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{DD758D21-E5D5-4D40-9450-5F65A32F359C}</ProjectGuid> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> @@ -141,6 +141,7 @@ <Compile Include="AttributeDescriptionFixture.cs" /> <Compile Include="AttributeInheritance.cs" /> <Compile Include="BasicRunnerTests.cs" /> + <Compile Include="ActionAttributeTests.cs" /> <Compile Include="CallContextTests.cs" /> <Compile Include="CategoryAttributeTests.cs" /> <Compile Include="CombinatorialTests.cs" /> === added directory 'src/NUnitFramework/framework/Interfaces' === added file 'src/NUnitFramework/framework/Interfaces/IAction.cs' --- src/NUnitFramework/framework/Interfaces/IAction.cs 1970-01-01 00:00:00 +0000 +++ src/NUnitFramework/framework/Interfaces/IAction.cs 2010-12-10 03:36:07 +0000 @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NUnit.Framework +{ + public interface IAction + { + } +} === added file 'src/NUnitFramework/framework/Interfaces/ISuiteAction.cs' --- src/NUnitFramework/framework/Interfaces/ISuiteAction.cs 1970-01-01 00:00:00 +0000 +++ src/NUnitFramework/framework/Interfaces/ISuiteAction.cs 2010-12-10 03:36:07 +0000 @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NUnit.Framework +{ + public interface ISuiteAction : IAction + { + void BeforeSuite(object fixture); + void AfterSuite(object fixture); + } +} === added file 'src/NUnitFramework/framework/Interfaces/ITestAction.cs' --- src/NUnitFramework/framework/Interfaces/ITestAction.cs 1970-01-01 00:00:00 +0000 +++ src/NUnitFramework/framework/Interfaces/ITestAction.cs 2010-12-10 03:36:07 +0000 @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; + +namespace NUnit.Framework +{ + public interface ITestAction : IAction + { + void BeforeTest(object fixture, MethodInfo method); + void AfterTest(object fixture, MethodInfo method); + } +} === modified file 'src/NUnitFramework/framework/nunit.framework.build' --- src/NUnitFramework/framework/nunit.framework.build 2010-12-09 18:18:45 +0000 +++ src/NUnitFramework/framework/nunit.framework.build 2010-12-10 03:36:07 +0000 @@ -1,7 +1,7 @@ <?xml version="1.0"?> <project name="NUnitFramework" default="build" basedir="."> - <patternset id="source-files"> + <patternset id="source-files"> <include name="Attributes/CategoryAttribute.cs"/> <include name="Attributes/DatapointAttributes.cs"/> <include name="Attributes/DescriptionAttribute.cs"/> @@ -75,6 +75,9 @@ <include name="Exceptions/IgnoreException.cs"/> <include name="Exceptions/InconclusiveException.cs"/> <include name="Exceptions/SuccessException.cs"/> + <include name="Interfaces/IAction.cs" /> + <include name="Interfaces/ISuiteAction.cs" /> + <include name="Interfaces/ITestAction.cs" /> <include name="AssemblyInfo.cs"/> <include name="Assert.cs"/> <include name="AssertionHelper.cs"/> @@ -101,6 +104,7 @@ <include name="Text.cs"/> <include name="TextMessageWriter.cs"/> <include name="Throws.cs"/> +<<<<<<< TREE </patternset> <target name="build"> @@ -141,4 +145,46 @@ </copy> </target> -</project> \ No newline at end of file +</project>======= + </patternset> + + <target name="build"> + + <csc target="library" + output="${current.framework.dir}/nunit.framework.dll" + doc="${current.framework.dir}/nunit.framework.xml" + debug="${build.debug}" + define="${build.defines}"> + <nowarn> + <warning number="618,672"/> + <warning number="1699" if="${runtime.version=='2.0'}"/> + </nowarn> + <sources basedir="."> + <patternset refid="source-files"/> + <include name="../../GeneratedAssemblyInfo.cs" /> + </sources> + </csc> + + <!-- Needed locally by some NUnit tests --> + <copy file="${current.framework.dir}/nunit.framework.dll" + todir="${current.test.dir}"/> + + <!-- Needed in base dir by pnunit tests --> + <copy file="${current.framework.dir}/nunit.framework.dll" + todir="${current.build.dir}"/> + + </target> + + <target name="package"> + <copy todir="${package.src.dir}/NUnitFramework/framework"> + <fileset> + <patternset refid="source-files"/> + <include name="nunit.framework.build"/> + <include name="nunit.framework.dll.csproj"/> + <include name="SyntaxElements.txt"/> + </fileset> + </copy> + </target> + +</project> +>>>>>>> MERGE-SOURCE === modified file 'src/NUnitFramework/framework/nunit.framework.dll.csproj' --- src/NUnitFramework/framework/nunit.framework.dll.csproj 2010-11-07 15:49:05 +0000 +++ src/NUnitFramework/framework/nunit.framework.dll.csproj 2010-12-10 03:36:07 +0000 @@ -1,8 +1,8 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5"> <PropertyGroup> <ProjectType>Local</ProjectType> - <ProductVersion>9.0.21022</ProductVersion> + <ProductVersion>9.0.30729</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{83DD7E12-A705-4DBA-9D71-09C8973D9382}</ProjectGuid> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> @@ -155,9 +155,12 @@ <Compile Include="FileAssert.cs" /> <Compile Include="GlobalSettings.cs" /> <Compile Include="Has.cs" /> + <Compile Include="Interfaces\IAction.cs" /> <Compile Include="IExpectException.cs" /> <Compile Include="Is.cs" /> + <Compile Include="Interfaces\ITestAction.cs" /> <Compile Include="ITestCaseData.cs" /> + <Compile Include="Interfaces\ISuiteAction.cs" /> <Compile Include="Iz.cs" /> <Compile Include="List.cs" /> <Compile Include="ListMapper.cs" /> === modified file 'src/NUnitFramework/tests/nunit.framework.tests.csproj' --- src/NUnitFramework/tests/nunit.framework.tests.csproj 2010-11-07 15:49:05 +0000 +++ src/NUnitFramework/tests/nunit.framework.tests.csproj 2010-12-10 03:36:07 +0000 @@ -1,8 +1,8 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5"> <PropertyGroup> <ProjectType>Local</ProjectType> - <ProductVersion>9.0.21022</ProductVersion> + <ProductVersion>9.0.30729</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{8C326431-AE57-4645-ACC1-A90A0B425129}</ProjectGuid> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> === added file 'src/tests/test-assembly/ActionAttributeFixture.cs' --- src/tests/test-assembly/ActionAttributeFixture.cs 1970-01-01 00:00:00 +0000 +++ src/tests/test-assembly/ActionAttributeFixture.cs 2010-12-10 03:36:07 +0000 @@ -0,0 +1,97 @@ +using System; +using System.Collections.Specialized; +using NUnit.Framework; +using System.Diagnostics; +using System.Reflection; +using NUnit.TestData.ActionAttributeTests; + +[assembly: SampleAction("Assembly")] + +namespace NUnit.TestData.ActionAttributeTests +{ + [SetUpFixture] + [SampleAction("SetUpFixture")] + public class SetupFixture + { + } + + [TestFixture] + [SampleAction("Fixture")] + public class ActionAttributeFixture : IWithAction + { + private static StringCollection _Results = null; + public static StringCollection Results + { + get { return _Results; } + set { _Results = value; } + } + + StringCollection IWithAction.Results { get { return Results; } } + + [Test, TestCase("SomeTest-Case1"), TestCase("SomeTest-Case2")] + [SampleAction("Method")] + public void SomeTest(string message) + { + ((IWithAction)this).Results.Add(message); + } + + [Test] + public void SomeOtherTest() + { + ((IWithAction)this).Results.Add("SomeOtherTest"); + } + + } + + [SampleAction("Interface")] + public interface IWithAction + { + StringCollection Results { get; } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Module, AllowMultiple = true, Inherited = true)] + public class SampleActionAttribute : Attribute, ISuiteAction, ITestAction + { + private string _Prefix = null; + + public SampleActionAttribute(string prefix) + { + _Prefix = prefix; + } + + void ISuiteAction.BeforeSuite(object fixture) + { + AddResult(fixture, null); + } + + void ISuiteAction.AfterSuite(object fixture) + { + AddResult(fixture, null); + } + + void ITestAction.BeforeTest(object fixture, MethodInfo method) + { + AddResult(fixture, method); + } + + void ITestAction.AfterTest(object fixture, MethodInfo method) + { + AddResult(fixture, method); + } + + private void AddResult(object fixture, MethodInfo method) + { + StackFrame frame = new StackFrame(1); + MethodBase actionMethod = frame.GetMethod(); + + string actionMethodName = actionMethod.Name.Substring(actionMethod.Name.LastIndexOf('.') + 1); + string message = string.Format("{0}.{1}-{2}" + (method != null ? "-{3}" : ""), + _Prefix, + actionMethodName, + fixture == null ? "{no-fixture}" : fixture.GetType().Name, + method != null ? method.Name : ""); + + ActionAttributeFixture.Results.Add(message); + } + } +} === modified file 'src/tests/test-assembly/test-assembly.csproj' --- src/tests/test-assembly/test-assembly.csproj 2010-11-07 15:49:05 +0000 +++ src/tests/test-assembly/test-assembly.csproj 2010-12-10 03:36:07 +0000 @@ -1,8 +1,8 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5"> <PropertyGroup> <ProjectType>Local</ProjectType> - <ProductVersion>9.0.21022</ProductVersion> + <ProductVersion>9.0.30729</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{1960CAC4-9A82-47C5-A9B3-55BC37572C3C}</ProjectGuid> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> @@ -126,6 +126,7 @@ </Compile> <Compile Include="AttributeDescriptionTests.cs" /> <Compile Include="AttributeInheritance.cs" /> + <Compile Include="ActionAttributeFixture.cs" /> <Compile Include="CategoryAttributeTests.cs" /> <Compile Include="ConsoleRunnerTest.cs" /> <Compile Include="CultureAttributeTests.cs" />
_______________________________________________ Mailing list: https://launchpad.net/~nunit-core Post to : nunit-core@lists.launchpad.net Unsubscribe : https://launchpad.net/~nunit-core More help : https://help.launchpad.net/ListHelp