-2

I have a WPF application used to execute logic that tests hardware (i.e. reads sensors, amps, voltages, etc.)

Each individual test runs when a "Test Device" method is called. I need to be able to exit the method when one of the tests fails so that no further tests are run.

However, using an if statement results in a bunch of ugly, hard to read and hard to debug code. It's also not re-usable at all. I have a bunch of apps that do this for different hardware devices. It would be nice to have a library so testing and development were much faster. I've been reading about tasks, delegates, actions, and state management - but I'm not quite sure what to use and how to put it all together.

Edit - here is pseudo-code for what happens when a user clicks "start":

    public void ExecuteTests()
    {
        // Code that sets / resets test object state here
        ...
    
        RunTestOne();
        if(TestOne.Pass)
        {
            RunTestTwo();
            if(TestTwo.Pass)
            {
                RunTestThree();
                ...
            }
        }
        foreach(Test toCheck in _tests)
        {
            if(!toCheck.PassFailBool.HasValue)
            {
                toCheck.Fail;
            }
        }
    }
  • Does this answer your question? [Should I return from a function early or use an if statement?](https://softwareengineering.stackexchange.com/questions/18454/should-i-return-from-a-function-early-or-use-an-if-statement) – gnat Feb 08 '21 at 19:45
  • 1
    Unit test framework achieve that by throwing exceptions, which is a language feature that resembles your use case quite closely if I understood it correctly. Would that be an option for you? – null Feb 08 '21 at 20:36
  • 2
    I am not sure I understand the question. Code would help. Can you provide an example showing how you'd do what you ask using the ugly `if` statements? – John Wu Feb 08 '21 at 21:15
  • A task will do nicely. The main point is to have your tests executed by a separate thread. Have the thread run your tests and wait for them to complete. Call RunTests (in the worker thread) in a try-catch block. If any test fails, just throw. After the try-catch block your thread or task will end (the thread method returns). You UI thread should be signaled somehow when the test thread completes/finishes. It should also be signaled by an event when each individual test ends (fails or succeeds) so you can show progress. The task framework has good support for what you are trying to do. – Martin Maat Feb 08 '21 at 22:04
  • A task, action or delegate does seem to help resolve the issue. I need to be able to reflect the state of the action, delegate, or task once it completes, dependent on the outcome. The state is reflected in the UI, then reported via web API as XML. State is used to track hardware failure rates, and prevent bad hardware from being shipped. Further more, I might have a test that, say, programs a device. If the device fails to program, none of the other tests are going to pass since the device won't work properly. So I need to bail from the method. – Dink McDinkleman Feb 09 '21 at 17:26

2 Answers2

1

You're looking for "early exit" or "return early."

Example (for demonstration purposes only; won't win any beauty contests):

int Tests()
{
   if (!TestOne())
       return 1;

   if (!TestTwo())
       return 2;

   // as many times as you need.

   return 0;

}

You can also put all of your tests as delegates into a Dictionary, run a loop over the dictionary, and break when one of your tests fails.

bool RunAllTests()
{    
    var tests = new Dictionary<string, Action<bool>()
    {
       {"Test1", () => Test1() };
       {"Test2", () => Test2() };
    }

    foreach(var test in tests)
    {
        if (!test.Value())
           return false;
    }
    return true;
}
Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
1

If your test methods return a Boolean, you can just chain them with &&, which will stop evaluating with the first one that returns false.

var pass = TestOne() && TestTwo() && TestThree() && TestFour();
John Wu
  • 26,032
  • 10
  • 63
  • 84