1 // ***********************************************************************
2 // Copyright (c) 2012-2015 Charlie Poole
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 // ***********************************************************************
25 #define NUNIT_FRAMEWORK
30 using System.Reflection;
31 using NUnit.Compatibility;
32 using NUnit.Framework.Interfaces;
34 namespace NUnit.Framework.Internal
37 /// The Test abstract class represents a test within the framework.
39 public abstract class Test : ITest, IComparable
44 /// Static value to seed ids. It's started at 1000 so any
45 /// uninitialized ids will stand out.
47 private static int _nextID = 1000;
50 /// The SetUp methods.
52 protected MethodInfo[] setUpMethods;
55 /// The teardown methods
57 protected MethodInfo[] tearDownMethods;
60 /// Used to cache the declaring type for this MethodInfo
62 protected ITypeInfo DeclaringTypeInfo;
65 /// Method property backing field
67 private IMethodInfo _method;
74 /// Constructs a test given its name
76 /// <param name="name">The name of the test</param>
77 protected Test( string name )
79 Guard.ArgumentNotNullOrEmpty(name, "name");
85 /// Constructs a test given the path through the
86 /// test hierarchy to its parent and a name.
88 /// <param name="pathName">The parent tests full name</param>
89 /// <param name="name">The name of the test</param>
90 protected Test( string pathName, string name )
92 Guard.ArgumentNotNullOrEmpty(pathName, "pathName");
96 FullName = pathName + "." + name;
100 /// TODO: Documentation needed for constructor
102 /// <param name="typeInfo"></param>
103 protected Test(ITypeInfo typeInfo)
105 Initialize(typeInfo.GetDisplayName());
107 string nspace = typeInfo.Namespace;
108 if (nspace != null && nspace != "")
109 FullName = nspace + "." + Name;
114 /// Construct a test from a MethodInfo
116 /// <param name="method"></param>
117 protected Test(IMethodInfo method)
119 Initialize(method.Name);
122 TypeInfo = method.TypeInfo;
123 FullName = method.TypeInfo.FullName + "." + Name;
126 private void Initialize(string name)
128 FullName = Name = name;
130 Properties = new PropertyBag();
131 RunState = RunState.Runnable;
134 private static string GetNextId()
136 return IdPrefix + unchecked(_nextID++);
141 #region ITest Members
144 /// Gets or sets the id of the test
147 public string Id { get; set; }
150 /// Gets or sets the name of the test
152 public string Name { get; set; }
155 /// Gets or sets the fully qualified name of the test
158 public string FullName { get; set; }
161 /// Gets the name of the class where this test was declared.
162 /// Returns null if the test is not associated with a class.
164 public string ClassName
168 ITypeInfo typeInfo = TypeInfo;
172 if (DeclaringTypeInfo == null)
173 DeclaringTypeInfo = new TypeWrapper(Method.MethodInfo.DeclaringType);
175 typeInfo = DeclaringTypeInfo;
178 if (typeInfo == null)
181 return typeInfo.IsGenericType
182 ? typeInfo.GetGenericTypeDefinition().FullName
188 /// Gets the name of the method implementing this test.
189 /// Returns null if the test is not implemented as a method.
191 public virtual string MethodName
197 /// Gets the TypeInfo of the fixture used in running this test
198 /// or null if no fixture type is associated with it.
200 public ITypeInfo TypeInfo { get; private set; }
203 /// Gets a MethodInfo for the method implementing this test.
204 /// Returns null if the test is not implemented as a method.
206 public IMethodInfo Method
208 get { return _method; }
211 DeclaringTypeInfo = null;
214 } // public setter needed by NUnitTestCaseBuilder
217 /// Whether or not the test should be run
219 public RunState RunState { get; set; }
222 /// Gets the name used for the top-level element in the
223 /// XML representation of this test
225 public abstract string XmlElementName { get; }
228 /// Gets a string representing the type of test. Used as an attribute
229 /// value in the XML representation of a test and has no other
230 /// function in the framework.
232 public virtual string TestType
234 get { return this.GetType().Name; }
238 /// Gets a count of test cases represented by
239 /// or contained under this test.
241 public virtual int TestCaseCount
247 /// Gets the properties for this test
249 public IPropertyBag Properties { get; private set; }
252 /// Returns true if this is a TestSuite
256 get { return this is TestSuite; }
260 /// Gets a bool indicating whether the current test
261 /// has any descendant tests.
263 public abstract bool HasChildren { get; }
266 /// Gets the parent as a Test object.
267 /// Used by the core to set the parent.
269 public ITest Parent { get; set; }
272 /// Gets this test's child tests
274 /// <value>A list of child tests</value>
275 public abstract System.Collections.Generic.IList<ITest> Tests { get; }
278 /// Gets or sets a fixture object for running this test.
280 public virtual object Fixture { get; set; }
284 #region Other Public Properties
287 /// Static prefix used for ids in this AppDomain.
288 /// Set by FrameworkController.
290 public static string IdPrefix { get; set; }
293 /// Gets or Sets the Int value representing the seed for the RandomGenerator
296 public int Seed { get; set; }
300 #region Internal Properties
302 internal bool RequiresThread { get; set; }
304 internal bool IsAsynchronous { get; set; }
308 #region Other Public Methods
311 /// Creates a TestResult for this test.
313 /// <returns>A TestResult suitable for this type of test.</returns>
314 public abstract TestResult MakeTestResult();
318 /// Modify a newly constructed test by applying any of NUnit's common
319 /// attributes, based on a supplied ICustomAttributeProvider, which is
320 /// usually the reflection element from which the test was constructed,
321 /// but may not be in some instances. The attributes retrieved are
322 /// saved for use in subsequent operations.
324 /// <param name="provider">An object deriving from MemberInfo</param>
325 public void ApplyAttributesToTest(MemberInfo provider)
327 //foreach (IApplyToTest iApply in provider.GetAttributes<IApplyToTest>(true))
328 // iApply.ApplyToTest(this);
332 /// Modify a newly constructed test by applying any of NUnit's common
333 /// attributes, based on a supplied ICustomAttributeProvider, which is
334 /// usually the reflection element from which the test was constructed,
335 /// but may not be in some instances. The attributes retrieved are
336 /// saved for use in subsequent operations.
338 /// <param name="provider">An object deriving from MemberInfo</param>
339 public void ApplyAttributesToTest(Assembly provider)
341 //foreach (IApplyToTest iApply in provider.GetAttributes<IApplyToTest>())
342 // iApply.ApplyToTest(this);
346 /// Modify a newly constructed test by applying any of NUnit's common
347 /// attributes, based on a supplied ICustomAttributeProvider, which is
348 /// usually the reflection element from which the test was constructed,
349 /// but may not be in some instances. The attributes retrieved are
350 /// saved for use in subsequent operations.
352 /// <param name="provider">An object implementing ICustomAttributeProvider</param>
353 public void ApplyAttributesToTest(ICustomAttributeProvider provider)
355 foreach (IApplyToTest iApply in provider.GetCustomAttributes(typeof(IApplyToTest), true))
356 iApply.ApplyToTest(this);
362 #region Protected Methods
365 /// Add standard attributes and members to a test node.
367 /// <param name="thisNode"></param>
368 /// <param name="recursive"></param>
369 protected void PopulateTestNode(TNode thisNode, bool recursive)
371 thisNode.AddAttribute("id", this.Id.ToString());
372 thisNode.AddAttribute("name", this.Name);
373 thisNode.AddAttribute("fullname", this.FullName);
374 if (this.MethodName != null)
375 thisNode.AddAttribute("methodname", this.MethodName);
376 if (this.ClassName != null)
377 thisNode.AddAttribute("classname", this.ClassName);
378 thisNode.AddAttribute("runstate", this.RunState.ToString());
380 if (Properties.Keys.Count > 0)
381 Properties.AddToXml(thisNode, recursive);
386 #region IXmlNodeBuilder Members
389 /// Returns the Xml representation of the test
391 /// <param name="recursive">If true, include child tests recursively</param>
392 /// <returns></returns>
393 public TNode ToXml(bool recursive)
395 return AddToXml(new TNode("dummy"), recursive);
399 /// Returns an XmlNode representing the current result after
400 /// adding it as a child of the supplied parent node.
402 /// <param name="parentNode">The parent node.</param>
403 /// <param name="recursive">If true, descendant results are included</param>
404 /// <returns></returns>
405 public abstract TNode AddToXml(TNode parentNode, bool recursive);
409 #region IComparable Members
412 /// Compares this test to another test for sorting purposes
414 /// <param name="obj">The other test</param>
415 /// <returns>Value of -1, 0 or +1 depending on whether the current test is less than, equal to or greater than the other test</returns>
416 public int CompareTo(object obj)
418 Test other = obj as Test;
423 return this.FullName.CompareTo(other.FullName);