Index: TestFixtureAttribute.cs
===================================================================
--- TestFixtureAttribute.cs	(revision 64)
+++ TestFixtureAttribute.cs	(working copy)
@@ -19,9 +19,9 @@
     [RunFactory(typeof(CombinatorialRun))]
 	public sealed class TestFixtureAttribute : TestFixturePatternAttribute 
 	{
-        private static volatile Object syncRoot = new Object();
-        private static SequenceRun runs = null;
-        private static ParallelRun testRuns = null;
+        private static readonly Object syncRoot = new Object();
+        private static IRun runs = null;
+
         /// <summary>
 		/// Default constructor
 		/// </summary>
@@ -53,52 +53,12 @@
 		/// <include file="MbUnit.Framework.doc.xml" path="doc/examples/example[@name='GraphicsBitmap']"/>
 		public override IRun GetRun()
 		{
-            if (runs != null)
-                    return runs;
             lock (syncRoot)
             {
-                CreateRun();
+                if (runs == null)
+                    runs = new TestFixtureRun();
+                return runs;
             }
-            return runs;
         }
-
-        public static ParallelRun TestRuns
-        {
-            get
-            {
-                lock (syncRoot)
-                {
-                    if (runs == null)
-                        CreateRun();
-                    return testRuns;
-                }
-            }
-        }
-
-        private static SequenceRun CreateRun()
-        {
-            runs = new SequenceRun();
-
-            // setup
-            OptionalMethodRun setup = new OptionalMethodRun(typeof(SetUpAttribute), false);
-            runs.Runs.Add(setup);
-
-            testRuns = new ParallelRun();
-            runs.Runs.Add(testRuns);
-
-            foreach (RunFactoryAttribute runFactory in
-                typeof(TestFixtureAttribute).GetCustomAttributes(typeof(RunFactoryAttribute), true)
-                )
-            {
-                IRun run = runFactory.CreateRun();
-                testRuns.Runs.Add(run);
-            }
-
-            // tear down
-            OptionalMethodRun tearDown = new OptionalMethodRun(typeof(TearDownAttribute), false);
-            runs.Runs.Add(tearDown);
-
-            return runs;
-        }
     }
 }
Index: TestFixtureExtensionAttribute.cs
===================================================================
--- TestFixtureExtensionAttribute.cs	(revision 0)
+++ TestFixtureExtensionAttribute.cs	(revision 0)
@@ -0,0 +1,46 @@
+using System;
+using MbUnit.Core.Collections;
+using MbUnit.Core.Framework;
+using MbUnit.Framework;
+
+namespace MbUnit.Framework 
+{
+	/// <summary>
+	/// Contributes additional tests and setup or teardown steps to the
+    /// lifecycle defined by <see cref="TestFixtureAttribute" />.
+	/// </summary>
+	[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)]
+	public abstract class TestFixtureExtensionAttribute : PatternAttribute
+	{
+        public TestFixtureExtensionAttribute()
+		{}
+
+        public TestFixtureExtensionAttribute(string description)
+			: base(description)
+		{}
+
+        /// <summary>
+        /// Called to add runs to perform before setup.
+        /// </summary>
+        /// <param name="runs">The collection to update</param>
+        public virtual void AddBeforeSetupRuns(RunCollection runs)
+        {
+        }
+
+        /// <summary>
+        /// Called to add runs to perform during the test execution cycle.
+        /// </summary>
+        /// <param name="runs">The collection to update</param>
+        public virtual void AddTestRuns(RunCollection runs)
+        {
+        }
+
+        /// <summary>
+        /// Called to add runs to perform after teardown.
+        /// </summary>
+        /// <param name="runs">The collection to update</param>
+        public virtual void AddAfterTearDownRuns(RunCollection runs)
+        {
+        }
+    }
+}
Index: Core/Runs/TestFixtureRun.cs
===================================================================
--- Core/Runs/TestFixtureRun.cs	(revision 0)
+++ Core/Runs/TestFixtureRun.cs	(revision 0)
@@ -0,0 +1,125 @@
+// MbUnit Test Framework
+// 
+// Copyright (c) 2004 Jonathan de Halleux
+//
+// 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 in the product 
+//		documentation would be appreciated but is not required.
+//
+//		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.
+//		
+//		MbUnit HomePage: http://www.mbunit.org
+//		Author: Jonathan de Halleux
+
+
+using System;
+using MbUnit.Core.Invokers;
+using MbUnit.Framework;
+
+namespace MbUnit.Core.Runs
+{
+	/// <summary>
+	/// Test fixture run with support for decoration by
+    /// <see cref="TestFixtureExtensionAttribute" />.
+	/// </summary>
+    [RunFactory(typeof(TestRun))]
+    [RunFactory(typeof(RowRun))]
+    [RunFactory(typeof(CombinatorialRun))]
+    public sealed class TestFixtureRun : IRun
+	{
+        private static readonly object syncRoot = new object();
+        private static IRun setupRun;
+        private static IRun tearDownRun;
+        private static IRun[] testRuns;
+
+		public bool IsTest
+		{
+			get
+            {
+                return false;
+            }
+		}
+		
+		public string Name
+		{
+			get
+			{
+				return "TestFixture";
+			}
+		}
+		
+        /// <summary>
+        /// Builds the test run invoker tree.
+        /// </summary>
+        /// <param name="tree"></param>
+        /// <param name="parent"></param>
+        /// <param name="t"></param>
+		public void Reflect(RunInvokerTree tree, RunInvokerVertex parent, Type t)
+		{
+            // Cache these runs because we reuse them for every test fixture.
+            lock (syncRoot)
+            {
+                if (tearDownRun == null)
+                {
+                    setupRun = new OptionalMethodRun(typeof(SetUpAttribute), false);
+
+                    object[] factories = GetType().GetCustomAttributes(typeof(RunFactoryAttribute), true);
+                    testRuns = new IRun[factories.Length];
+                    for (int i = 0; i < factories.Length; i++)
+                        testRuns[i] = ((RunFactoryAttribute) factories[i]).CreateRun();
+
+                    tearDownRun = new OptionalMethodRun(typeof(TearDownAttribute), false);
+                }
+            }
+
+            // Build the sequence including any extensions and apply it.
+            CreateSequence(t).Reflect(tree, parent, t);
+        }
+
+        private IRun CreateSequence(Type t)
+        {
+            SequenceRun seq = new SequenceRun();
+            object[] extensions = t.GetCustomAttributes(typeof(TestFixtureExtensionAttribute), true);
+
+            // Before Setup (extensions)
+            foreach (TestFixtureExtensionAttribute extension in extensions)
+                extension.AddBeforeSetupRuns(seq.Runs);
+
+            // Setup
+            seq.Runs.Add(setupRun);
+
+            // Tests
+            ParallelRun tests = new ParallelRun();
+            seq.Runs.Add(tests);
+
+            foreach (IRun testRun in testRuns)
+                tests.Runs.Add(testRun);
+
+            // Tests (extensions)
+            foreach (TestFixtureExtensionAttribute extension in extensions)
+                extension.AddTestRuns(tests.Runs);
+
+            // TearDown
+            seq.Runs.Add(tearDownRun);
+
+            // After TearDown (extensions)
+            foreach (TestFixtureExtensionAttribute extension in extensions)
+                extension.AddAfterTearDownRuns(seq.Runs);
+
+            return seq;
+		}
+	}
+}
