How to test different classes using one interface?

I have an iSome interface. have 4 classes such as MyClass1: ISome, MyClass2: ISome, etc. How to test some method from this interface using NUnit, but do only 1 unit test for all classes?

+4
source share
5 answers

4 classes mean 4 different implementations of this method. As a result, you should have 4 unit tests. It would be wrong to try writing one unit test.

+4
source

How to test some method from this interface using NUnit, but do only 1 unit test for all classes?

As you wrote this, people can interpret it as a “single unit test, period”. This, of course, is a very bad idea.

Ideally, you want to make only one statement for each test case, and you really need to assert all the different parts of the logic in your code. Each class will have more than one part of the logic, and each implementation of your interface is a completely different part of the logic (even if it has the same interface and even if you copy and paste the code).

So, you are faced with one of the options: you need some unit tests.

Code duplication

To avoid duplication of unit test code, you can try the parameterized functions of unit test NUnit.

With it, you can multiply the number of unit test methods that you actually write by the number of instances you submitted to these tests. These instances may be different implementations.

There are many ways to parameterize your tests in NUnit. See this article:

I personally prefer the TestCaseSource attribute:

The NUnit tester will still display every unit test method you wrote, but will display every element in your dataset as a subtest.

It's hard to figure out how to use it because you need to test your data-driven model.

How to parameterize an implementation

If your implementations of this method in your interface just spit out different data, you might be lucky. For instance. if you test multiplication in one implementation and addition in another method, your matrix may look like this:

 Impl Input1 Input2 Result Multiply 0 7 0 Multiply 3 6 18 Add 0 0 0 Add 5 6 11 

You will return an array that embodies each row in this matrix, including the implementation of your interface with which you work, submit them to one unit test method, which represents the general flow of the test and names it.

Here is an example of code that implements the following operations:

 // This interface takes two ints, returns one int public interface IBinaryOperation { int Execute(int x, int y); string Name { get; } } public class Add : IBinaryOperation { public int Execute(int x, int y) { return x + y; } public string Name { get { return "Add"; } } } public class Multiply : IBinaryOperation { public int Execute(int x, int y) { return x * y; } public string Name { get { return "Multiply"; } } } 

And here is an example implementation of a test adapter:

 [Test, TestCaseSource("OperationTestCases")] public void ExecuteReturnsCorrectResult( IBinaryOperation operation, int inputX, int inputY, int expectedResult ) { int actualResult = operation.Execute(inputX, inputY); Assert.That(actualResult, Is.EqualTo(expectedResult), "Expected operation: '{0}', with '{1}' and '{2}' to return '{3}'" , operation.Name , inputX , inputY , expectedResult ); } static object[] OperationTestCases = { new object[] { new Multiply(), 0, 7, 0 }, new object[] { new Multiply(), 3, 6, 18 }, new object[] { new Add(), 0, 0, 0 }, new object[] { new Add(), 5, 6, 11 }, }; 

Results from running this test suite in NUnit

More complex examples

If your implementations are more diverse from each other, or you cannot create a simple input / output matrix, it will be more difficult for you.

One option is to submit delegates to the test file. But it is so complicated, unclear and difficult to maintain as it sounds. In that case, you really should write separate unit test methods.

+3
source

Darin Dimitrov is generally right, but for convenience you can implement one abstract test case for all implementations. Having an abstract method like

 protected abstract ISome createInstance(); 

and override it in test cases inherited from your abstract test class.

+2
source

you can check out the interface of Greg Young: NUnit plugin: https://github.com/gregoryyoung/grensesnitt

+1
source

You should not associate the number of unit tests you create with the number of classes in your code. Ideally, you would like to at least cover as many code paths as you can, and as many different scripts that you can think of. Heuristics usually should give you more than one unit test per class. In your case, you should have at least 4, but you will need to write a lot more (for non-trivial code) to really implement the code in a meaningful way.

0
source

Source: https://habr.com/ru/post/1379792/


All Articles