#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig /************************************************************************************ ' ' Copyright © 2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole ' Copyright © 2000-2003 Philip A. Craig ' ' This software is provided 'as-is', without any express or implied warranty. In no ' event will the authors be held liable for any damages arising from the use of this ' software. ' ' Permission is granted to anyone to use this software for any purpose, including ' commercial applications, and to alter it and redistribute it freely, subject to the ' following restrictions: ' ' 1. The origin of this software must not be misrepresented; you must not claim that ' you wrote the original software. If you use this software in a product, an ' acknowledgment (see the following) in the product documentation is required. ' ' Portions Copyright © 2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole ' or Copyright © 2000-2003 Philip A. Craig ' ' 2. Altered source versions must be plainly marked as such, and must not be ' misrepresented as being the original software. ' ' 3. This notice may not be removed or altered from any source distribution. ' '***********************************************************************************/ #endregion namespace NUnit.Core { using System; using System.Reflection; using System.Collections; /// /// Summary description for TestCaseBuilder. /// public class TestCaseBuilder { private static Hashtable builders; private static ITestBuilder normalBuilder = new NormalBuilder(); private static void InitBuilders() { builders = new Hashtable(); builders[typeof(NUnit.Framework.ExpectedExceptionAttribute)] = new ExpectedExceptionBuilder(); } private static ITestBuilder GetBuilder(MethodInfo method) { if (builders == null) InitBuilders(); object[] attributes = method.GetCustomAttributes(false); foreach (object attribute in attributes) { ITestBuilder builder = (ITestBuilder) builders[attribute.GetType()]; if (builder != null) return builder; } return normalBuilder; } public static TestCase Make(object fixture, MethodInfo method) { TestCase testCase = null; if(HasTestAttribute(method) || HasObsoleteTestName(method) && !HasAnySetUpOrTearDownAttribute(method) ) { if(IsTestMethodSignatureCorrect(method)) { ITestBuilder builder = GetBuilder(method); testCase = builder.Make(fixture, method); if(HasIgnoreAttribute(method)) { testCase.ShouldRun = false; testCase.IgnoreReason = GetIgnoreReason(method); } if (HasCategoryAttribute(method)) { IList categories = GetCategories(method); CategoryManager.Add(categories); testCase.Categories = categories; } testCase.IsExplicit = HasExplicitAttribute(method); testCase.Description = GetDescription(method); } else { testCase = new NotRunnableTestCase(method); } } return testCase; } public static TestCase Make(object fixture, string methodName) { MethodInfo [] methods = fixture.GetType().GetMethods(BindingFlags.NonPublic|BindingFlags.Public|BindingFlags.Instance); foreach(MethodInfo method in methods) { if(method.Name.Equals(methodName)) return Make(fixture, method); } return null; } private static bool IsExpectedException(MethodInfo method) { Type exceptionAttr = typeof(NUnit.Framework.ExpectedExceptionAttribute); object[] attributes = method.GetCustomAttributes(exceptionAttr, false); return attributes.Length == 1; } private static NUnit.Framework.ExpectedExceptionAttribute GetExpectedExceptions(MethodInfo method) { Type exceptionAttr = typeof(NUnit.Framework.ExpectedExceptionAttribute); object[] attributes = method.GetCustomAttributes(exceptionAttr, false); NUnit.Framework.ExpectedExceptionAttribute expectedAttr = null; if(attributes.Length == 1) { expectedAttr = (NUnit.Framework.ExpectedExceptionAttribute)attributes[0]; } return expectedAttr; } private static string GetDescription(MethodInfo method) { Type testAttr = typeof(NUnit.Framework.TestAttribute); object[] attributes = method.GetCustomAttributes(testAttr, false); string description = null; if(attributes.Length == 1) { NUnit.Framework.TestAttribute attribute = (NUnit.Framework.TestAttribute)attributes[0]; description = attribute.Description; } return description; } public static int CountTestCases(object fixture) { int testCases = 0; MethodInfo [] methods = fixture.GetType().GetMethods(); foreach(MethodInfo method in methods) { if(IsTestMethod(method)) testCases++; } return testCases; } public static bool IsTestMethod(MethodInfo methodToCheck) { return (HasTestAttribute(methodToCheck) || HasObsoleteTestName(methodToCheck)) && IsTestMethodSignatureCorrect(methodToCheck); } private static bool IsTestMethodSignatureCorrect(MethodInfo methodToCheck) { return !methodToCheck.IsStatic && !methodToCheck.IsAbstract && methodToCheck.IsPublic && methodToCheck.GetParameters().Length == 0 && methodToCheck.ReturnType.Equals(typeof(void)); } private static bool HasTestAttribute(MethodInfo methodToCheck) { return methodToCheck.IsDefined(typeof(NUnit.Framework.TestAttribute),false); } private static bool HasObsoleteTestName(MethodInfo methodToCheck) { return methodToCheck.Name.ToLower().StartsWith("test"); } private static bool HasAnySetUpOrTearDownAttribute( MethodInfo methodToCheck ) { object[] attributes = methodToCheck.GetCustomAttributes( false ); foreach( Attribute attribute in attributes ) if ( attribute is NUnit.Framework.SetUpAttribute || attribute is NUnit.Framework.TestFixtureSetUpAttribute || attribute is NUnit.Framework.TearDownAttribute || attribute is NUnit.Framework.TestFixtureTearDownAttribute ) return true; return false; } private static bool HasIgnoreAttribute(MethodInfo methodToCheck) { Type ignoreMethodAttribute = typeof(NUnit.Framework.IgnoreAttribute); object[] attributes = methodToCheck.GetCustomAttributes(ignoreMethodAttribute, false); return attributes.Length == 1; } private static string GetIgnoreReason(MethodInfo methodToCheck) { Type ignoreMethodAttribute = typeof(NUnit.Framework.IgnoreAttribute); NUnit.Framework.IgnoreAttribute[] attributes = (NUnit.Framework.IgnoreAttribute[])methodToCheck.GetCustomAttributes(ignoreMethodAttribute, false); string result = "no reason"; if(attributes.Length > 0) result = attributes[0].Reason; return result; } private static bool HasCategoryAttribute(MethodInfo methodToCheck) { object[] attributes = methodToCheck.GetCustomAttributes(typeof(NUnit.Framework.CategoryAttribute), false); return attributes.Length > 0; } private static bool HasExplicitAttribute(MethodInfo methodToCheck) { object[] attributes = methodToCheck.GetCustomAttributes(typeof(NUnit.Framework.ExplicitAttribute), false); return attributes.Length > 0; } private static IList GetCategories(MethodInfo methodToCheck) { object[] attributes = methodToCheck.GetCustomAttributes(typeof(NUnit.Framework.CategoryAttribute), false); ArrayList list = new ArrayList(); foreach (NUnit.Framework.CategoryAttribute attrib in attributes) { list.Add(attrib.Name); } return list; } } internal interface ITestBuilder { TestCase Make(object fixture, MethodInfo method); } internal class ExpectedExceptionBuilder : ITestBuilder { #region ITestBuilder Members public TestCase Make(object fixture, MethodInfo method) { NUnit.Framework.ExpectedExceptionAttribute expectedException = GetExpectedExceptions(method); TestCase testCase = new ExpectedExceptionTestCase(fixture, method, expectedException.ExceptionType, expectedException.ExpectedMessage); return testCase; } #endregion private static NUnit.Framework.ExpectedExceptionAttribute GetExpectedExceptions(MethodInfo method) { Type exceptionAttr = typeof(NUnit.Framework.ExpectedExceptionAttribute); object[] attributes = method.GetCustomAttributes(exceptionAttr, false); NUnit.Framework.ExpectedExceptionAttribute expectedAttr = null; if(attributes.Length == 1) { expectedAttr = (NUnit.Framework.ExpectedExceptionAttribute)attributes[0]; } return expectedAttr; } } internal class NormalBuilder : ITestBuilder { #region ITestBuilder Members public TestCase Make(object fixture, MethodInfo method) { return new NormalTestCase(fixture, method); } #endregion } }