Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,201 @@
// ****************************************************************
// 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/?p=license&r=2.4.
// ****************************************************************
using System;
using System.Collections;
using System.Reflection;
namespace NUnit.Core.Builders
{
/// <summary>
/// AbstractFixtureBuilder may serve as a base class for
/// implementing a suite builder. It provides a templated
/// implementation of the BuildFrom method as well as a
/// number of useful methods that derived classes may use.
/// </summary>
public abstract class AbstractFixtureBuilder : Extensibility.ISuiteBuilder
{
#region Instance Fields
/// <summary>
/// The TestSuite being constructed;
/// </summary>
protected TestSuite suite;
/// <summary>
/// The fixture builder's own test case builder collection
/// </summary>
protected Extensibility.TestCaseBuilderCollection testCaseBuilders =
new Extensibility.TestCaseBuilderCollection(CoreExtensions.Host);
#endregion
#region Abstract Methods
/// <summary>
/// Examine the type and determine if it is suitable for
/// this builder to use in building a TestSuite.
///
/// Note that returning false will cause the type to be ignored
/// in loading the tests. If it is desired to load the suite
/// but label it as non-runnable, ignored, etc., then this
/// method must return true.
/// </summary>
/// <param name="type">The type of the fixture to be used</param>
/// <returns>True if the type can be used to build a TestSuite</returns>
public abstract bool CanBuildFrom(Type type);
/// <summary>
/// Method that actually creates a new TestSuite object
///
/// Derived classes must override this method.
/// </summary>
/// <param name="type">The user fixture type</param>
/// <returns></returns>
protected abstract TestSuite MakeSuite( Type type );
#endregion
#region Virtual Methods
/// <summary>
/// Templated implementaton of ISuiteBuilder.BuildFrom. Any
/// derived builder may choose to override this method in
/// it's entirety or to let it stand and override some of
/// the virtual methods that it calls.
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public virtual Test BuildFrom(Type type)
{
this.suite = MakeSuite(type);
SetTestSuiteProperties(type, suite);
AddTestCases(type);
if ( this.suite.RunState != RunState.NotRunnable && this.suite.TestCount == 0)
{
this.suite.RunState = RunState.NotRunnable;
this.suite.IgnoreReason = suite.TestName.Name + " does not have any tests";
}
return this.suite;
}
/// <summary>
/// Method that sets properties of the test suite based on the
/// information in the provided Type.
///
/// Derived classes normally override this method and should
/// call the base method or include equivalent code.
/// </summary>
/// <param name="type">The type to examine</param>
/// <param name="suite">The test suite being constructed</param>
protected virtual void SetTestSuiteProperties( Type type, TestSuite suite )
{
string reason = null;
if (!IsValidFixtureType(type, ref reason) )
{
this.suite.RunState = RunState.NotRunnable;
this.suite.IgnoreReason = reason;
}
}
/// <summary>
/// Virtual method that returns true if the fixture type is valid
/// for use by the builder. If not, it returns false and sets
/// reason to an appropriate message. As implemented in this class,
/// the method checks that a default constructor is available. You
/// may override this method in a derived class in order to make
/// different or additional checks.
/// </summary>
/// <param name="fixtureType">The fixture type</param>
/// <param name="reason">The reason this fixture is not valid</param>
/// <returns>True if the fixture type is valid, false if not</returns>
protected virtual bool IsValidFixtureType( Type fixtureType, ref string reason )
{
if (fixtureType.IsAbstract)
{
reason = string.Format("{0} is an abstract class", fixtureType.FullName);
return false;
}
if (Reflect.GetConstructor(fixtureType) == null)
{
reason = string.Format( "{0} does not have a valid constructor", fixtureType.FullName );
return false;
}
return true;
}
/// <summary>
/// Method to add test cases to the newly constructed suite.
/// The default implementation looks at each candidate method
/// and tries to build a test case from it. It will only need
/// to be overridden if some other approach, such as reading a
/// datafile is used to generate test cases.
/// </summary>
/// <param name="fixtureType"></param>
protected virtual void AddTestCases( Type fixtureType )
{
IList methods = GetCandidateTestMethods( fixtureType );
foreach(MethodInfo method in methods)
{
Test test = BuildTestCase(method);
if(test != null)
{
this.suite.Add( test );
}
}
}
/// <summary>
/// Method to create a test case from a MethodInfo and add
/// it to the suite being built. It first checks to see if
/// any global TestCaseBuilder addin wants to build the
/// test case. If not, it uses the internal builder
/// collection maintained by this fixture builder. After
/// building the test case, it applies any decorators
/// that have been installed.
///
/// The default implementation has no test case builders.
/// Derived classes should add builders to the collection
/// in their constructor.
/// </summary>
/// <param name="method"></param>
/// <returns></returns>
protected virtual Test BuildTestCase( MethodInfo method )
{
// TODO: Review order of using builders
Test test = CoreExtensions.Host.TestBuilders.BuildFrom( method );
if ( test == null && this.testCaseBuilders.CanBuildFrom( method ) )
test = this.testCaseBuilders.BuildFrom( method );
if ( test != null )
test = CoreExtensions.Host.TestDecorators.Decorate( test, method );
return test;
}
/// <summary>
/// Method to return all methods in a fixture that should be examined
/// to see if they are test methods. The default returns all methods
/// of the fixture: public and private, instance and static, declared
/// and inherited.
///
/// While this method may be overridden, it should normally not be.
/// If it is overridden to eliminate certain methods, they will be
/// silently ignored. Generally, it is better to include them in the
/// list and let the TestCaseBuilders decide how to handle them.
/// </summary>
/// <param name="fixtureType"></param>
/// <returns></returns>
protected IList GetCandidateTestMethods( Type fixtureType )
{
return fixtureType.GetMethods( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static );
}
#endregion
}
}

View File

@@ -0,0 +1,105 @@
// ****************************************************************
// 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/?p=license&r=2.4.
// ****************************************************************
using System.Reflection;
namespace NUnit.Core.Builders
{
/// <summary>
/// AbstractTestCaseBuilder may serve as a base class for
/// implementing a test case builder. It provides a templated
/// implementation of the BuildFrom method.
///
/// Developers of extended test cases may choose to inherit
/// from this class, although NUnitTestCaseBuilder will
/// probably be more useful if the extension is intended
/// to work like an NUnit test case.
/// </summary>
public abstract class AbstractTestCaseBuilder : Extensibility.ITestCaseBuilder
{
#region Instance Fields
protected int runnerID;
protected TestCase testCase;
#endregion
#region Abstract Methods
/// <summary>
/// Examine the method and determine if it is suitable for
/// this builder to use in building a TestCase.
///
/// Note that returning false will cause the method to be ignored
/// in loading the tests. If it is desired to load the method
/// but label it as non-runnable, ignored, etc., then this
/// method must return true.
///
/// Derived classes must override this method.
/// </summary>
/// <param name="method">The test method to examine</param>
/// <returns>True is the builder can use this method</returns>
public abstract bool CanBuildFrom(System.Reflection.MethodInfo method);
/// <summary>
/// Method that actually creates a new test case object.
///
/// Derived classes must override this method.
/// </summary>
/// <param name="method">The test method to examine</param>
/// <returns>An object derived from TestCase</returns>
protected abstract TestCase MakeTestCase( MethodInfo method );
/// <summary>
/// Method that sets properties of the test case based on the
/// information in the provided MethodInfo.
///
/// Derived classes must override this method.
/// </summary>
/// <param name="method">The test method to examine</param>
/// <param name="testCase">The test case being constructed</param>
protected abstract void SetTestProperties( MethodInfo method, TestCase testCase );
#endregion
#region Virtual Methods
/// <summary>
/// Templated implementaton of ITestCaseBuilder.BuildFrom.
///
/// Any derived builder may choose to override this method in
/// it's entirety or to let it stand and override some of
/// the virtual methods that it calls.
/// </summary>
/// <param name="method">The method for which a test case is to be built</param>
/// <returns>A TestCase or null</returns>
public virtual Test BuildFrom(System.Reflection.MethodInfo method)
{
if ( !HasValidTestCaseSignature( method ) )
return new NotRunnableTestCase( method );
TestCase testCase = MakeTestCase( method );
if ( testCase != null )
SetTestProperties( method , testCase );
return testCase;
}
/// <summary>
/// Virtual method that checks the signature of a potential test case to
/// determine if it is valid. The default implementation requires methods
/// to be public, non-abstract instance methods, taking no parameters and
/// returning void. Methods not meeting these criteria will be marked by
/// NUnit as non-runnable.
/// </summary>
/// <param name="method">The method to be checked</param>
/// <returns>True if the method signature is valid, false if not</returns>
protected virtual bool HasValidTestCaseSignature( MethodInfo method )
{
return !method.IsStatic
&& !method.IsAbstract
&& method.IsPublic
&& method.GetParameters().Length == 0
&& method.ReturnType.Equals(typeof(void) );
}
#endregion
}
}

View File

@@ -0,0 +1,26 @@
// ****************************************************************
// 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/?p=license&r=2.4.
// ****************************************************************
using System;
namespace NUnit.Core.Builders
{
/// <summary>
/// Built-in SuiteBuilder for LegacySuite
/// </summary>
public class LegacySuiteBuilder : Extensibility.ISuiteBuilder
{
public bool CanBuildFrom( Type type )
{
return LegacySuite.GetSuiteProperty( type ) != null;
}
public Test BuildFrom( Type type )
{
return new LegacySuite( type );
}
}
}

View File

@@ -0,0 +1,76 @@
// ****************************************************************
// 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/?p=license&r=2.4.
// ****************************************************************
using System;
using System.Reflection;
using System.Collections;
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using System.Configuration;
using System.Diagnostics;
namespace NUnit.Core.Builders
{
public class NUnitTestCaseBuilder : AbstractTestCaseBuilder
{
private bool allowOldStyleTests = NUnitFramework.AllowOldStyleTests;
#region AbstractTestCaseBuilder Overrides
/// <summary>
/// Determine if the method is an NUnit test method.
/// The method must normally be marked with the test
/// attribute for this to be true. If the test config
/// file sets AllowOldStyleTests to true, then any
/// method beginning "test..." (case-insensitive)
/// is treated as a test unless it is also marked
/// as a setup or teardown method.
/// </summary>
/// <param name="method">A MethodInfo for the method being used as a test method</param>
/// <returns>True if the builder can create a test case from this method</returns>
public override bool CanBuildFrom(MethodInfo method)
{
if ( Reflect.HasAttribute( method, NUnitFramework.TestAttribute, false ) )
return true;
if (allowOldStyleTests)
{
Regex regex = new Regex("^(?i:test)");
if ( regex.Match(method.Name).Success
&& !NUnitFramework.IsSetUpMethod( method )
&& !NUnitFramework.IsTearDownMethod( method )
&& !NUnitFramework.IsFixtureSetUpMethod( method )
&& !NUnitFramework.IsFixtureTearDownMethod( method ) )
return true;
}
return false;
}
/// <summary>
/// Create an NUnitTestMethod
/// </summary>
/// <param name="method">A MethodInfo for the method being used as a test method</param>
/// <returns>A new NUnitTestMethod</returns>
protected override TestCase MakeTestCase(MethodInfo method)
{
return new NUnitTestMethod( method );
}
/// <summary>
/// Set additional properties of the newly created test case based
/// on its attributes. As implemented, the method sets the test's
/// RunState, Description, Categories and Properties.
/// </summary>
/// <param name="method">A MethodInfo for the method being used as a test method</param>
/// <param name="testCase">The test case being constructed</param>
protected override void SetTestProperties( MethodInfo method, TestCase testCase )
{
NUnitFramework.ApplyCommonAttributes( method, testCase );
NUnitFramework.ApplyExpectedExceptionAttribute( method, (TestMethod)testCase );
}
#endregion
}
}

View File

@@ -0,0 +1,129 @@
// ****************************************************************
// 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/?p=license&r=2.4.
// ****************************************************************
using System;
using System.Collections;
using System.Reflection;
using System.Text.RegularExpressions;
namespace NUnit.Core.Builders
{
/// <summary>
/// Built-in SuiteBuilder for NUnit TestFixture
/// </summary>
public class NUnitTestFixtureBuilder : AbstractFixtureBuilder
{
public NUnitTestFixtureBuilder()
{
this.testCaseBuilders.Install( new NUnitTestCaseBuilder() );
}
#region AbstractFixtureBuilder Overrides
/// <summary>
/// Makes an NUnitTestFixture instance
/// </summary>
/// <param name="type">The type to be used</param>
/// <returns>An NUnitTestFixture as a TestSuite</returns>
protected override TestSuite MakeSuite( Type type )
{
return new NUnitTestFixture( type );
}
/// <summary>
/// Method that sets properties of the test suite based on the
/// information in the provided Type.
/// </summary>
/// <param name="type">The type to examine</param>
/// <param name="suite">The test suite being constructed</param>
protected override void SetTestSuiteProperties( Type type, TestSuite suite )
{
base.SetTestSuiteProperties( type, suite );
NUnitFramework.ApplyCommonAttributes( type, suite );
}
/// <summary>
/// Checks to see if the fixture type has the test fixture
/// attribute type specified in the parameters. Override
/// to allow additional types - based on name, for example.
/// </summary>
/// <param name="type">The fixture type to check</param>
/// <returns>True if the fixture can be built, false if not</returns>
public override bool CanBuildFrom(Type type)
{
return Reflect.HasAttribute( type, NUnitFramework.TestFixtureAttribute, true );
}
/// <summary>
/// Check that the fixture is valid. In addition to the base class
/// check for a valid constructor, this method ensures that there
/// is no more than one of each setup or teardown method and that
/// their signatures are correct.
/// </summary>
/// <param name="fixtureType">The type of the fixture to check</param>
/// <param name="reason">A message indicating why the fixture is invalid</param>
/// <returns>True if the fixture is valid, false if not</returns>
protected override bool IsValidFixtureType(Type fixtureType, ref string reason)
{
if (!base.IsValidFixtureType(fixtureType, ref reason))
return false;
if (!fixtureType.IsPublic && !fixtureType.IsNestedPublic)
{
reason = "Fixture class is not public";
return false;
}
return CheckSetUpTearDownMethod(fixtureType, "SetUp", NUnitFramework.SetUpAttribute, ref reason)
&& CheckSetUpTearDownMethod(fixtureType, "TearDown", NUnitFramework.TearDownAttribute, ref reason)
&& CheckSetUpTearDownMethod(fixtureType, "TestFixtureSetUp", NUnitFramework.FixtureSetUpAttribute, ref reason)
&& CheckSetUpTearDownMethod(fixtureType, "TestFixtureTearDown", NUnitFramework.FixtureTearDownAttribute, ref reason);
}
/// <summary>
/// Internal helper to check a single setup or teardown method
/// </summary>
/// <param name="fixtureType">The type to be checked</param>
/// <param name="attributeName">The short name of the attribute to be checked</param>
/// <returns>True if the method is present no more than once and has a valid signature</returns>
private bool CheckSetUpTearDownMethod(Type fixtureType, string name, string attributeName, ref string reason)
{
int count = Reflect.CountMethodsWithAttribute(
fixtureType, attributeName,
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly,
true);
if (count == 0) return true;
if (count > 1)
{
reason = string.Format("More than one {0} method", name);
return false;
}
MethodInfo theMethod = Reflect.GetMethodWithAttribute(
fixtureType, attributeName,
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly,
true);
if (theMethod != null)
{
if (theMethod.IsStatic ||
theMethod.IsAbstract ||
!theMethod.IsPublic && !theMethod.IsFamily ||
theMethod.GetParameters().Length != 0 ||
!theMethod.ReturnType.Equals(typeof(void)))
{
reason = string.Format("Invalid {0} method signature", name);
return false;
}
}
return true;
}
#endregion
}
}

View File

@@ -0,0 +1,35 @@
// ****************************************************************
// 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/?p=license&r=2.4.
// ****************************************************************
using System;
namespace NUnit.Core.Builders
{
/// <summary>
/// SetUpFixtureBuilder knows how to build a SetUpFixture.
/// </summary>
public class SetUpFixtureBuilder : Extensibility.ISuiteBuilder
{
public SetUpFixtureBuilder()
{
//
// TODO: Add constructor logic here //
}
#region ISuiteBuilder Members
public Test BuildFrom(Type type)
{
return new SetUpFixture( type );
}
public bool CanBuildFrom(Type type)
{
return Reflect.HasAttribute( type, NUnitFramework.SetUpFixtureAttribute, false );
}
#endregion
}
}

View File

@@ -0,0 +1,213 @@
// ****************************************************************
// 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/?p=license&r=2.4.
// ****************************************************************
using System;
using System.IO;
using System.Collections;
using System.Reflection;
using NUnit.Core.Extensibility;
namespace NUnit.Core.Builders
{
/// <summary>
/// Class that builds a TestSuite from an assembly
/// </summary>
public class TestAssemblyBuilder
{
#region Instance Fields
/// <summary>
/// The loaded assembly
/// </summary>
Assembly assembly;
/// <summary>
/// Our LegacySuite builder, which is only used when a
/// fixture has been passed by name on the command line.
/// </summary>
ISuiteBuilder legacySuiteBuilder;
private TestAssemblyInfo assemblyInfo = null;
#endregion
#region Properties
public Assembly Assembly
{
get { return assembly; }
}
public TestAssemblyInfo AssemblyInfo
{
get
{
if ( assemblyInfo == null && assembly != null )
{
string path = TestFixtureBuilder.GetAssemblyPath( assembly );
AssemblyReader rdr = new AssemblyReader( path );
Version runtimeVersion = new Version( rdr.ImageRuntimeVersion.Substring( 1 ) );
IList frameworks = CoreExtensions.Host.TestFrameworks.GetReferencedFrameworks( assembly );
assemblyInfo = new TestAssemblyInfo( path, runtimeVersion, frameworks );
}
return assemblyInfo;
}
}
#endregion
#region Constructor
public TestAssemblyBuilder()
{
// TODO: Keeping this separate till we can make
//it work in all situations.
legacySuiteBuilder = new NUnit.Core.Builders.LegacySuiteBuilder();
}
#endregion
#region Build Methods
public Test Build( string assemblyName, string testName, bool autoSuites )
{
if ( testName == null || testName == string.Empty )
return Build( assemblyName, autoSuites );
this.assembly = Load( assemblyName );
if ( assembly == null ) return null;
// If provided test name is actually the name of
// a type, we handle it specially
Type testType = assembly.GetType(testName);
if( testType != null )
return Build( 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 );
return null;
}
public TestSuite Build( string assemblyName, bool autoSuites )
{
this.assembly = Load( assemblyName );
if ( this.assembly == null ) return null;
IList fixtures = GetFixtures( assembly, null );
return BuildTestAssembly( assemblyName, fixtures, autoSuites );
}
private Test Build( 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
// whether to allow them in more places.
if ( legacySuiteBuilder.CanBuildFrom( testType ) )
return legacySuiteBuilder.BuildFrom( testType );
else if ( TestFixtureBuilder.CanBuildFrom( testType ) )
return BuildTestAssembly( assemblyName,
new Test[] { TestFixtureBuilder.BuildFrom( testType ) }, autoSuites );
return null;
}
private TestSuite BuildTestAssembly( string assemblyName, IList fixtures, bool autoSuites )
{
TestSuite testAssembly = new TestSuite( assemblyName );
if ( autoSuites )
{
NamespaceTreeBuilder treeBuilder =
new NamespaceTreeBuilder( testAssembly );
treeBuilder.Add( fixtures );
testAssembly = treeBuilder.RootSuite;
}
else
foreach( TestSuite fixture in fixtures )
{
if ( fixture is SetUpFixture )
{
fixture.RunState = RunState.NotRunnable;
fixture.IgnoreReason = "SetUpFixture cannot be used when loading tests as a flat list of fixtures";
}
testAssembly.Add( fixture );
}
if ( fixtures.Count == 0 )
{
testAssembly.RunState = RunState.NotRunnable;
testAssembly.IgnoreReason = "Has no TestFixtures";
}
NUnitFramework.ApplyCommonAttributes( assembly, testAssembly );
// TODO: Make this an option? Add Option to sort assemblies as well?
testAssembly.Sort();
return testAssembly;
}
#endregion
#region Helper Methods
private Assembly Load(string path)
{
Assembly assembly = null;
// Change currentDirectory in case assembly references unmanaged dlls
using( new DirectorySwapper( Path.GetDirectoryName( path ) ) )
{
// Throws if this isn't a managed assembly or if it was built
// with a later version of the same assembly.
AssemblyName.GetAssemblyName( Path.GetFileName( path ) );
// TODO: Figure out why we can't load using the assembly name
// in all cases. Might be a problem with the tests themselves.
assembly = Assembly.Load(Path.GetFileNameWithoutExtension(path));
if ( assembly != null )
CoreExtensions.Host.InstallAdhocExtensions( assembly );
NTrace.Info( "Loaded assembly " + assembly.FullName, "'TestAssemblyBuilder'" );
return assembly;
}
}
private IList GetFixtures( Assembly assembly, string ns )
{
ArrayList fixtures = new ArrayList();
IList testTypes = GetCandidateFixtureTypes( assembly, ns );
foreach(Type testType in testTypes)
{
if( TestFixtureBuilder.CanBuildFrom( testType ) )
fixtures.Add( TestFixtureBuilder.BuildFrom( testType ) );
}
return fixtures;
}
private IList GetCandidateFixtureTypes( Assembly assembly, string ns )
{
IList types = assembly.GetTypes();
if ( ns == null || ns == string.Empty || types.Count == 0 )
return types;
string prefix = ns + "." ;
ArrayList result = new ArrayList();
foreach( Type type in types )
if ( type.FullName.StartsWith( prefix ) )
result.Add( type );
return result;
}
#endregion
}
}