I don't think this is an example of composite pattern. Composite is defined as
The Composite Pattern allows you to compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
Main idea of Composite is to allow treating whole (several parts) as a individual part. I.e. when client asks Composite to do something, then it means that Composite will ask all it's Components to do same thing. But neither Setup nor Teardown methods of your Composite do not touch collection of TestElements. So, you simply have set of classes with some base class, but that is not Composite.
If you would like to treat TestSequence or TestPlan as a single Test then it would be a Composite. I.e. if you would add Run functionality to your base class (or interface)
public interface ITest
{
void Run();
}
and TestSequence would run all it's tests:
public class TestSequence : ITest
{
private IList<ITest> tests = new List<ITest>();
public void Run()
{
Setup();
foreach(var test in tests)
test.Run();
Teardown();
}
public void Setup()
{
Console.WriteLine("Setup executed for Test " + Id);
}
public void Teardown()
{
Console.WriteLine("Teardown executed for Test " + Id);
}
}
Then TestSequence would be a Composite, because it's completely transparent for client whether it works with single part (Test) or with a whole (TestSequence, collection of Tests). Same with TestPlan - you can treat it as a single TestSequence. Thus you can treat TestSequence as single Test, then for client TestPlan can also be treated as single Test. Client can run TestPlan, and it will run all it's test sequences, which in their turn will run all tests.