1 // ***********************************************************************
2 // Copyright (c) 2009 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
29 using System.Collections;
30 using System.Collections.Generic;
32 namespace NUnit.Framework.Internal.Builders
35 /// Class that can build a tree of automatic namespace
36 /// suites from a group of fixtures.
38 public class NamespaceTreeBuilder
40 #region Instance Variables
43 /// NamespaceDictionary of all test suites we have created to represent
44 /// namespaces. Used to locate namespace parent suites for fixtures.
46 Dictionary<string, TestSuite> namespaceSuites = new Dictionary<string, TestSuite>();
49 /// The root of the test suite being created by this builder.
58 /// Initializes a new instance of the <see cref="NamespaceTreeBuilder"/> class.
60 /// <param name="rootSuite">The root suite.</param>
61 public NamespaceTreeBuilder( TestSuite rootSuite )
63 this.rootSuite = rootSuite;
71 /// Gets the root entry in the tree created by the NamespaceTreeBuilder.
73 /// <value>The root suite.</value>
74 public TestSuite RootSuite
76 get { return rootSuite; }
81 #region Public Methods
84 /// Adds the specified fixtures to the tree.
86 /// <param name="fixtures">The fixtures to be added.</param>
87 public void Add( IList<Test> fixtures )
89 foreach (TestSuite fixture in fixtures)
90 //if (fixture is SetUpFixture)
91 // Add(fixture as SetUpFixture);
97 /// Adds the specified fixture to the tree.
99 /// <param name="fixture">The fixture to be added.</param>
100 public void Add( TestSuite fixture )
102 string ns = GetNamespaceForFixture(fixture);
103 TestSuite containingSuite = BuildFromNameSpace( ns );
105 if (fixture is SetUpFixture)
106 AddSetUpFixture(fixture, containingSuite, ns);
108 containingSuite.Add( fixture );
113 #region Helper Method
115 private static string GetNamespaceForFixture(TestSuite fixture)
117 string ns = fixture.FullName;
118 int index = ns.IndexOfAny(new char[] { '[', '(' });
119 if (index >= 0) ns = ns.Substring(0, index);
120 index = ns.LastIndexOf('.');
121 ns = index > 0 ? ns.Substring(0, index) : string.Empty;
125 private TestSuite BuildFromNameSpace( string ns )
127 if( ns == null || ns == "" ) return rootSuite;
129 TestSuite suite = namespaceSuites.ContainsKey(ns)
130 ? namespaceSuites[ns]
136 int index = ns.LastIndexOf(".");
139 suite = new TestSuite( ns );
140 if ( rootSuite == null )
143 rootSuite.Add(suite);
147 string parentNamespace = ns.Substring( 0,index );
148 TestSuite parent = BuildFromNameSpace( parentNamespace );
149 string suiteName = ns.Substring( index+1 );
150 suite = new TestSuite( parentNamespace, suiteName );
154 namespaceSuites[ns] = suite;
158 private void AddSetUpFixture(TestSuite newSetupFixture, TestSuite containingSuite, string ns)
160 // The SetUpFixture must replace the namespace suite
161 // in which it is "contained".
163 // First, add the old suite's children
164 foreach (TestSuite child in containingSuite.Tests)
165 newSetupFixture.Add(child);
167 if (containingSuite is SetUpFixture)
169 // The parent suite is also a SetupFixture. The new
170 // SetupFixture is nested below the parent SetupFixture.
171 // TODO: Avoid nesting of SetupFixtures somehow?
173 // Note: The tests have already been copied to the new
174 // SetupFixture. Thus the tests collection of
175 // the parent SetupFixture can be cleared.
176 containingSuite.Tests.Clear();
177 containingSuite.Add(newSetupFixture);
181 // Make the parent of the containing suite point to this
183 // TODO: Get rid of this somehow?
184 TestSuite parent = (TestSuite)containingSuite.Parent;
187 newSetupFixture.Name = rootSuite.Name;
188 rootSuite = newSetupFixture;
192 parent.Tests.Remove(containingSuite);
193 parent.Add(newSetupFixture);
197 // Update the dictionary
198 namespaceSuites[ns] = newSetupFixture;