1 // ***********************************************************************
2 // Copyright (c) 2007 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.Collections.Generic;
31 using System.Reflection;
32 using NUnit.Framework.Interfaces;
33 using NUnit.Framework.Internal.Commands;
35 #if NET_4_0 || NET_4_5 || PORTABLE
36 using System.Threading.Tasks;
39 namespace NUnit.Framework.Internal
42 /// TestSuite represents a composite test, which contains other tests.
44 public class TestSuite : Test
49 /// Our collection of child tests
51 private List<ITest> tests = new List<ITest>();
58 /// Initializes a new instance of the <see cref="TestSuite"/> class.
60 /// <param name="name">The name of the suite.</param>
61 public TestSuite(string name) : base(name)
63 Arguments = new object[0];
67 /// Initializes a new instance of the <see cref="TestSuite"/> class.
69 /// <param name="parentSuiteName">Name of the parent suite.</param>
70 /// <param name="name">The name of the suite.</param>
71 public TestSuite(string parentSuiteName, string name)
72 : base(parentSuiteName, name)
74 Arguments = new object[0];
78 /// Initializes a new instance of the <see cref="TestSuite"/> class.
80 /// <param name="fixtureType">Type of the fixture.</param>
81 public TestSuite(ITypeInfo fixtureType)
84 Arguments = new object[0];
88 /// Initializes a new instance of the <see cref="TestSuite"/> class.
90 /// <param name="fixtureType">Type of the fixture.</param>
91 public TestSuite(Type fixtureType)
92 : base(new TypeWrapper(fixtureType))
94 Arguments = new object[0];
99 #region Public Methods
102 /// Sorts tests under this suite.
106 if (!MaintainTestOrder)
110 foreach (Test test in Tests)
112 TestSuite suite = test as TestSuite;
121 /// Sorts tests under this suite using the specified comparer.
123 /// <param name="comparer">The comparer.</param>
124 public void Sort(IComparer comparer)
126 this.tests.Sort(comparer);
128 foreach( Test test in Tests )
130 TestSuite suite = test as TestSuite;
132 suite.Sort(comparer);
138 /// Adds a test to the suite.
140 /// <param name="test">The test.</param>
141 public void Add(Test test)
152 /// Gets this test's child tests
154 /// <value>The list of child tests</value>
155 public override IList<ITest> Tests
157 get { return tests; }
161 /// Gets a count of test cases represented by
162 /// or contained under this test.
165 public override int TestCaseCount
171 foreach (Test test in Tests)
173 count += test.TestCaseCount;
180 /// The arguments to use in creating the fixture
182 public object[] Arguments { get; internal set; }
185 /// Set to true to suppress sorting this suite's contents
187 protected bool MaintainTestOrder { get; set; }
191 #region Test Overrides
194 /// Overridden to return a TestSuiteResult.
196 /// <returns>A TestResult for this test.</returns>
197 public override TestResult MakeTestResult()
199 return new TestSuiteResult(this);
203 /// Gets a bool indicating whether the current test
204 /// has any descendant tests.
206 public override bool HasChildren
210 return tests.Count > 0;
215 /// Gets the name used for the top-level element in the
216 /// XML representation of this test
218 public override string XmlElementName
220 get { return "test-suite"; }
224 /// Returns an XmlNode representing the current result after
225 /// adding it as a child of the supplied parent node.
227 /// <param name="parentNode">The parent node.</param>
228 /// <param name="recursive">If true, descendant results are included</param>
229 /// <returns></returns>
230 public override TNode AddToXml(TNode parentNode, bool recursive)
232 TNode thisNode = parentNode.AddElement("test-suite");
233 thisNode.AddAttribute("type", this.TestType);
235 PopulateTestNode(thisNode, recursive);
236 thisNode.AddAttribute("testcasecount", this.TestCaseCount.ToString());
240 foreach (Test test in this.Tests)
241 test.AddToXml(thisNode, recursive);
248 #region Helper Methods
251 /// Check that setup and teardown methods marked by certain attributes
252 /// meet NUnit's requirements and mark the tests not runnable otherwise.
254 /// <param name="attrType">The attribute type to check for</param>
255 protected void CheckSetUpTearDownMethods(Type attrType)
257 foreach (MethodInfo method in Reflect.GetMethodsWithAttribute(TypeInfo.Type, attrType, true))
258 if (method.IsAbstract ||
259 !method.IsPublic && !method.IsFamily ||
260 method.GetParameters().Length > 0 ||
261 method.ReturnType != typeof(void)
262 #if NET_4_0 || NET_4_5 || PORTABLE
264 method.ReturnType != typeof(Task)
269 PropertyNames.SkipReason,
270 string.Format("Invalid signature for SetUp or TearDown method: {0}", method.Name));
271 this.RunState = RunState.NotRunnable;