0

I have a project and am right now at a point, where it's growing complexity forces me to think about it's structure. To explain it in a few sentences:

  • I have a main application as UI. It allows the user to run different tests and should display status updates and results.
  • I have a whole bunch of classes containing different tests on some hardware. All those classes implement an iTest interface to ensure compatibility.

Where I am right now: I want to have status updates (which I don't get right now). I need some kind of StatusUpdate-Event fired in the Test-Classes and receive those events in my UI. I'm new to delegates and event handlers so I have no clue which way is the best to choose for this. Following the answer from here "How to add an event to a class" means I'd have to add a event handler each time I instantiate one of my test classes. That would generate a whole load of redundant code that I think is unnecessary.

I'd like to have one function in my UI named sth. like "StatusUpdateEventHandler(string textToDisplay)". It should not matter, which Test-Class invokes this event.

Can anyone give me some direction where to go at? Thank's a lot :)

Community
  • 1
  • 1
AllDayPiano
  • 414
  • 1
  • 4
  • 20
  • Question there can all these test classes be merged together into one or could they be sub classes of one parent class? (From your description I take it that these are NOT unit tests but instead classes that are there to generate the output which is shown in the UI?) – Thomas Nov 26 '15 at 14:31
  • 1
    Hi Thomas, I suppose you got the point. All test classes contain complete different hardware interaction and therefore are seperated. Simply said, one test could be "Switch on light bulb -> measure brightness -> switch off light buld". So far, i can update the status by saying "Test started" and "Test successfull" but cannot update like "Switching off successful". I have also thought about creating a base class but I'm still not really familiar with the abilities of C#.Net. – AllDayPiano Nov 26 '15 at 14:36
  • @AllDayPiano My first tought was creating a base class that all your tests that report progress should implements. In that base class, you set up an event that have a status update arguments that you can use in the UI to show progress (such as % completed and current step). – Gabriel Mongeon Nov 26 '15 at 15:39

2 Answers2

1

I'll use a base class that have common properties/methods/events to report progress back to the UI. Quickly, this is how I would approach the problem:

Create an event Handler to report progress:

public delegate void StatusChangedEventHandler(object sender, StatusChangedEventArgs e);

Create an abstract base class:

public abstract class TestBase:ITest
{

    // An event that clients can use to be notified whenever the
    // elements of the list change.
    public event StatusChangedEventHandler StatusChanged;
    protected virtual void OnStatusChanged(StatusChangedEventArgs e)
    {
        if (StatusChanged != null)
            StatusChanged(this, e);
    }

    protected virtual void ReportProgress (int percentage, string step)
    {
        OnStatusChanged(new StatusChangedEventArgs()
        {
            Percentage = percentage,
            Step = step
        });
    }

    public abstract void Execute();

}

Create a EventArgs that will be used to get data from the event in your UI:

public class StatusChangedEventArgs:EventArgs
{
    public int Percentage { get; set; }
    public string Step { get; set; }    
}

Then make sure that your tests use the base test class:

public class SimpleTest : TestBase
{
    public override void Execute()
    {
        ReportProgress(10, "STEP 1");
        ReportProgress(25, "STEP 2");
        ReportProgress(55, "STEP 3");
        ReportProgress(70, "STEP 4");
        ReportProgress(100, "STEP 5");

    }
}

Then hook up the event to your UI, here's my implementation in a console application:

class Program
{
    static void Main(string[] args)
    {
        SimpleTest simpleTest = new SimpleTest();

        simpleTest.StatusChanged += SimpleTest_StatusChanged;

        simpleTest.Execute();

        Console.ReadLine();

    }

    private static void SimpleTest_StatusChanged(object sender, StatusChangedEventArgs e)
    {
        Console.WriteLine($"{e.Percentage} - {e.Step}");
    }
}
Gabriel Mongeon
  • 7,251
  • 3
  • 32
  • 35
  • A short question to your (good looking) solution: Does the base class realle implement the iTest Interface (that is implemented by the test-class)? Wouldn't that mean, that i have a double implementation? – AllDayPiano Nov 27 '15 at 06:24
  • If your base class implements the ITest interface then the test class that implements the base class will implicitly be implementing the ITest interface. No need then to reimplement the ITest interface in your test class. You can have other class that implements ITest without using the base class this way. – Gabriel Mongeon Nov 27 '15 at 11:15
  • Very well. Thank you so much! It works absolutely as I wanted it to :) – AllDayPiano Nov 30 '15 at 08:54
0

I couldn't say you provided a lot of info to suggest a really helpful response. :-) It seems to me you look for something like generic events, see example within the article. You'd subscribe to the events which are fired by the test units, so the relevant string is passed along with each particular event. Besides, you could consider some class hierarchy to support your test units.

Hope it brings you some fresh thoughts to find the direction.