My motivating case is hardware test automation. We have several different testers (benches of lab equipment that connect to the device under test (DUT)), and we write test configuration files which instruct the tester what series of tests to perform. The tests performed take in parameters from the configuration as well.At the moment the coupling between these is higher than I'd like, so I'm trying to find a good pattern to keep the logic for how we perform tests (tester object(s)) separate from what tests we wish to perform in any particular run (the configuration objects).The best I've come up with so far is as follows (syntax not verified, just getting the idea across):class TestStepConfig{    string Name;    // Parameters are tuple of parameter name to parameter value. If parameter is not truly a string, it will be converted to int, float, etc later.    IReadOnlyList<Tuple<string, string>> Parameters;}interface ITester{    // Return value is any data coming back from the test. First tuple element is result name, second is result value (I.E. Voltage,5.0)    List<Tuple<string, string>> RunTestStep(TestStepConfig config);}class NaiveSequencer{    List<TestStepConfig> configs;    ITester tester;    void RunFullTest()    {        foreach (var config in configs)            tester.RunTestStep(config);    }}The idea is that each tester has a set of atomic test steps it can run. It knows these steps by name, and the steps take in a set of parameters as per the Parameters field of the TestStepConfig. So, you pass in a TestStepConfig with the name of the desired step and the desired parameters, and the tester performs that test step.Thus, all any configuration scheme needs to do is determine which TestStepConfigs to feed into the tester, and all the tester needs to understand is how to execute these atomic TestSteps.What has me wary of this solution is that the TestStepConfig looks uncomfortably like re-implementing a method call (Name of method, Parameters to pass in). I don't want to implement the testers as an actual set of specific test this, test that methods because:There may be many, many such test steps available (anywhere from 20to over 100), leading to extremely large, rigid objects.Many of these tests may or may not be available depending on theparticular configuration of the bench (what equipment is available,etc). How a TestStep of a particular name is executed may changedepending on the setup (what part is being tested, etc)I need to be able to perform sequences of tests with many differenttesters, and I can't be re-writing the sequencing algorithms everytime there's a new tester just because it has a different interfaceFor these reason and more, the TestSteps I feel are much better modeled as a group of something similar to a Command Pattern (but with execute-time parameters) brought together by a factory and placed into a generic implementation of a ITester object, rather than modeled as compile-time methods of the Tester.Has anyone had to deal with a case like this before? Is there a better pattern than the one I've proposed above?
Pattern for interface between sequence executing object(s) and sequence configuration objects
c#;object oriented