same unit test for different implementations - java

Let's say I have two implementations of a search algorithm that return the same result for the same input. They both implement the same interface.
How can I use a single [TestClass] for testing both implementations, rather then create two test files with eventually the same logic ?
Can I tell MSUnit to launch one of the tests twice with different constructor parameter?
Perhaps I should (n)inject it somehow ?

Use an abstract test class:
[TestClass]
public abstract class SearchTests
{
private ISearcher _searcherUnderTest;
[TestSetup]
public void Setup()
{
_searcherUnderTest = CreateSearcher();
}
protected abstract ISearcher CreateSearcher();
[TestMethod]
public void Test1(){/*do stuff to _searcherUnderTest*/ }
// more tests...
[TestClass]
public class CoolSearcherTests : SearcherTests
{
protected override ISearcher CreateSearcher()
{
return new CoolSearcher();
}
}
[TestClass]
public class LameSearcherTests : SearcherTests
{
protected override ISearcher CreateSearcher()
{
return new LameSearcher();
}
}
}

You've tagged your question with NUnit, but you ask about MSTest. What you are asking about can be achieved with parameterized test fixtures in NUnit. I am not familiar enough with MSTest to suggest an equivalent approach there, and a quick search indicates that MSTest may not have this feature.
In NUnit you parameterize the test fixture by applying multiple [TestFixture(...)] attributes to the fixture class with different parameters. These parameters will be passed to the fixture constructor.
Since there are limits on the types of parameter that can be passed, you'll probably need to pass a string in specifying the algorithm, then in the constructor assign the delegate or object that provides the search algorithm to a member field which is used in the tests.
For example:
using System;
using System.Collections.Generic;
using NUnit.Framework;
namespace MyTests
{
public static class SearchAlgorithms
{
public static int DefaultSearch(int target, IList<int> data)
{
return data.IndexOf(target);
}
public static int BrokenSearch(int target, IList<int> data)
{
return 789;
}
}
[TestFixture("forward")]
[TestFixture("broken")]
public class SearchTests
{
private Func<int, IList<int>, int> searchMethod;
public SearchTests(string algorithmName)
{
if (algorithmName == "forward")
{
this.searchMethod = SearchAlgorithms.DefaultSearch;
return;
}
if (algorithmName == "broken")
{
this.searchMethod = SearchAlgorithms.BrokenSearch;
}
}
[Test]
public void SearchFindsCorrectIndex()
{
Assert.AreEqual(
1, this.searchMethod(2, new List<int> { 1, 2, 3 }));
}
[Test]
public void SearchReturnsMinusOneWhenTargetNotPresent()
{
Assert.AreEqual(
-1, this.searchMethod(4, new List<int> { 1, 2, 3 }));
}
}
}

I'd rather have two different [TestMethod] in one [TestClass] each testing only one implementation: this way a failing test will always correctly point you which implementation went wrong.

If you are using NUnit you can pass through a variable declared in an attribute
http://www.nunit.org/index.php?p=testCase&r=2.5.6
if you use something like:
[TestCase(1)]
[TestCase(2)]
public void Test(int algorithm)
{
//..dostuff
}
if will run once for 1, once for 2, uses the same setup/teardown too :)
There isn't an equivalent in MSTest however you can fudge it somewhat as explained here:
Does MSTest have an equivalent to NUnit's TestCase?

I can't say I'm extremely happy with this approach, but here's what I ended up doing. I then went to look for a better approach and found this question. This approach meets the criteria, 1) I'm using MS Test, 2) I write the test logic only 1 time, 3) I can tell which implementation failed (and double clicking on the test will take me to the right test class).
This approach uses a base class to contain all the actual test logic, and then a derived class for each implementation (I have 3) that sets the specific implementation on the base interface and overrides the base test methods.
[TestClass]
public abstract class SearchTestBase
{
protected ISearcher Searcher { get; set; }
[TestMethod]
public virtual void Find_Results_Correct()
{
// Arrange (code here)
// Act (single line here)
var actual = Searcher.Results(input);
// Assert
}
}
(different file...)
[TestClass]
public class FastSearcherTest : SearcherTestBase
{
[TestInitialize]
public void TestInitialize()
{
Searcher = new FastSearcher();
}
[TestMethod]
public override void Find_Results_Correct()
{
base.Find_Results_Correct();
}
}
(different file...)
[TestClass]
public class ThoroughSearcherTest : SearcherTestBase
{
[TestInitialize]
public void TestInitialize()
{
Searcher = new ThoroughSearcher();
}
[TestMethod]
public override void Find_Results_Correct()
{
base.Find_Results_Correct();
}
}
So what I don't like about this approach is that every time I want to add a test I need to go to each of the test files and override the new test method. What I do like are the 3 requirements you had. If I need to change a test, I change the logic in just one place.
The advantage I see to this solution over the similar one of having a single method called by two tests is that I don't have to repeat the code for setting up the right implementation. In this solution you have a single line that calls the base.TestName(), and not two lines, one to set the Searcher and another to call the test. The Visual Studio also makes writing this much faster... I just type, "override" and get a list of choices. Auto complete writes the rest for me.

Clarifications based on my testing.
The accepted answer (to use an abstract class) works as long as the abstract class and concrete classes are in the same assembly.
If you desire to have the abstract class and concrete classes in different assemblies, the approach mentioned by KarlZ, unfortunately seems to be necessary. Not sure why this is the case. In this scenario, the TestExplorer will not show TestMethod.
Also, the accepted answer uses concrete classes nested within the abstract class. This does not appear to be a requirement.
Test with MSTestV2 (1.1.17), VS2017.
Here are sample classes used.
Assembly 1
[TestClass]
public abstract class SampleExternal
{
[TestMethod]
public void SampleTest01()
{
Assert.IsTrue(false, this.GetType().Name);
}
}
Assembly 2
[TestClass]
public abstract class Sample
{
[TestMethod]
public void SampleTest01()
{
Assert.IsTrue(false, this.GetType().Name);
}
[TestClass]
public class SampleA : Sample
{
}
}
[TestClass]
public class SampleB : Sample
{
}
[TestClass]
public class SampleC : SampleExternal
{
}
[TestClass]
public class SampleD : SampleExternal
{
}
using these, the test for SampleA and SampleB will execute (and fail by design), but SampleC & SampleD will not.

Related

Execution order of methods when #Test is at class level

There are a lot of questions on the execution order of TestNG tests, but I haven't found one that specifically answers this question - unless I just cannot find it.
I know there's things to do that can achieve what I'm looking for, such as:
#Test above every test method within the class with the use of Priority
#Test above every test method within the class with the use of Depends on
The use of preserve-order in the XML file
However, what I want to know is:
If you declare #Test at the class level, not the method level, how to "preserve" the order in which the methods are declared? Can you even do this?
For example, if my class looks like this:
#Test
public class mySampleClass
{
public void test()
{
//Run first - First method in the class
}
public void run()
{
//Run second - Second method in the class
}
public void execute()
{
//Run last - Last method in the class
}
}
Can I ensure that when I run this that the methods are executed in the order they are within the class instead of alphabetically?
Not sure why you want your tests to run that way, Even though it is not possible to do it directly, it IS possible using a MethodInterceptor:
public class MyInterceptor implements IMethodInterceptor {
// keep your list of method names in order
private static final List<String> order = List.of("test", "run", "execute");
#Override
public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
methods.sort(Comparator.comparing(m -> order.indexOf(m.getMethod().getMethodName())));
return methods;
}
}
Now add the #Listeners(value = MyInterceptor.class) annotation to your class.
NOTE: List.of is available only in java 9+, if you are using a lower version, you could use Arrays.asList.

Java Unit tests using Mockito. Function call within a function

Suppose I have the following class :
public class Math {
public int mult(int a, int b) {
return 4;
}
public int mul (int a, int b) {
return mult(a,b);
}
}
And the following test class :
public class TestMockito {
Math testMath;
#Before
public void create () {
testMath = *mock*(Math.class);
when(testMath.mult(1,2).thenReturn(2);
}
#Test
public void test() {
System.out.println(testMath.mul(1,2));
}
}
Why does mul(1,2) called in test() not use when(testMath.mult(1,2).thenReturn(2); ?
Is there any other way to mock a method being used inside another method that is being tested ?
Cheers
You usually do not mock the code under test (unless it is an abstract class).
You usually mock other classes (the dependencies) your CUT communicates with.
The reason why your test does not work (as you expect) is that the mock is not an object of the real class (which is the reason why we mock it BTW....). It has been derived by the mocking framework not to behave like the original code but like it has been configured for the test.
If you really want the real methods being called in the mock (which is not what you want most of the time) you need to tell mockito that when creating the mock:
mock(ClassToBeMocked.class,Mockito.CALL_REAL_METHODS);

Design Approach and Using Reflection to run methods in Java

I have a question. I have multiple classes in a package: Let's say package is
com.myPackage.first
And this package has the following classes:
firstGood
secondGood
thirdBad
fourthGood
Each of these classes have a method with the same name but different implementation. So say each have a one particular function called:
public void runMe(){
}
For now I want to come up with a way to given a class name, it'll go inside the class and run that particular method.
So conceptually, my method will look like those:
ArrayList<Class> classList ; // where classList is a list of classes I want to run
public void execute(){
for(Class c : classList){
// Go inside that class, (maybe create an intance of that class) and run the method called run me
}
}
or
public void execute(Class c, String methodToRun){
for(Class c : classList){
// Go inside that class, (maybe create an intance of that class) and run the method called run me
}
}
For now. what I have been able to do is get the name of the classes I want to run the
runMe()
method. So I have been able to come with a way to get the arraylist of classes I want to run. So what I need help with is coming up with a method such that it takes a class name and run the method I want it to. Any help is appreciated. Thanks
I suggest having a look at Class.forName ( ... ) to get the class object, Class.newInstance(); if your classes have a default constructor (or Class.getDeclaredConstructor(...) otherwise) to create a new instance and then Class.getDeclaredMethod( ... ) to find the method and invoke it.
All of this without any regard if your idea is really a good one, since I really didn't quite understand WHY you want to do what you want to do...
interface Me {
void runMe();
}
Then let all classes implement Me.
And have a list of Mes
List<Class<Me>> ...
Then
void test(Class<Me> cl) {
Me me = cl.newInstance();
me.runMe();
}
My adage is always use reflection to solve a problem - now you have two problems. In view of that have you considered a simple pattern like this:
interface Runner {
public void runMe();
}
static abstract class BaseRunner implements Runner {
public BaseRunner() {
// Automagically register all runners in the RunThem class.
RunThem.runners.add(this);
}
}
class FirstGood extends BaseRunner implements Runner {
#Override
public void runMe() {
System.out.println(this.getClass().getSimpleName() + ":runMe");
}
}
class SecondGood extends BaseRunner implements Runner {
#Override
public void runMe() {
System.out.println(this.getClass().getSimpleName() + ":runMe");
}
}
static class RunThem {
static final Set<Runner> runners = new HashSet<>();
static void runThem() {
for (Runner r : runners) {
r.runMe();
}
}
}
public void test() {
Runner f = new FirstGood();
Runner s = new SecondGood();
RunThem.runThem();
}
Here all of your runMe objects extend a base class whose constructor installs the object in a Set held by the class that calls their runMe methods.
inline
void execute() throws Exception{
for (Class<?> c : classesList)
{
//If you don't already have an instance then you need one
//note if the method is static no need for any existing instance.
Object obj = Class.forName(c.getName());
// name of the method and list of arguments to pass
Method m = c.getDeclaredMethod(methodName,null);
//method accessibility check
if(!m.isAccessible())
m.setAccessible(true);
//invoke method if method with arguements then pass them as new Object[]{arg0...} instead of null
//if method is static then m.innvoke(null,null)
m.invoke(obj, null);
}
}
I would recommend using an Interface that defines the runMe() method and then have all your classes implement that interface. Then you would have a list of this Interface:
List<MyInterface> classes = new ArrayList<MyInterface>();
Then you could easily iterate over it and invoke "runMe()" on all of them or if you only want to invoke it for instances of a certain class you could do it like this:
public void execute(Class classForWhichToExecute) {
for (MyInterface myInterface : classes) {
if (classForWhichToExecute.isAssignableForm(myInterface)) {
myInterface.runMe();
}
}
}
Of course this wouldn't work if your method is a static method - so adding more information from your side would help.
I would suggest to use an interface with a common method to override in each class. So that any class can be casted to interface and use its method to execute the method.
interface GoodAndBad{
public void runMe();
}
Implemented class
class FirstGood implements GoodAndBad{
#override
public void runMe(){
// Code to be executed
}
}
You can use execute() method as follows
public void execute(List<GoodAndBad> classList){
for(GoodAndBad c : classList){
c.runMe();
// Go inside that class, (maybe create an intance of that class) and
// run the method called run me
}
}
Change the Class to GoodAndBad interface to change the other method too.
This is loosely coupling objects to support favor over composition in Java Object Oriented Design Patterns.
Never use Strings of method names to execute a method at anytime. There are plenty of other cool solutions for that using design patterns.

The best way to test classes implementing the same interface

So, for example I have a few classes implementing the List<T> interface. How to test them - whether they implement the methods correctly?
Now I only see one way to do so:
public class MyListImplementationsTest {
private Collection<List<Integer>> listImplementations;
#BeforeClass
public static void setUp() throws Exception {
listImplementations = Arrays.asList(
new QuickList<Integer>(), new EfficientMemoryList<Integer>()
);
}
#Test
public void testIsEmptyAfterCreationEmptyList() {
// Use forEachList(handler) in order to not iterate
// the lists manually every time.
// May be there is no need to do so,
// because using <<for (item : items)>> instead of
// iterating using index prevents from OutOfBounds errors
forEachList(new OnEachListHandler<Integer>() {
#Override
public void onEach(List<Integer> list) {
assertTrue(list.isEmpty());
}
});
}
private <T> void forEachList(OnEachListHandler<T> handler) {
for (List<T> each : listImplementations) {
handler.onEach(each);
}
}
private static interface OnEachListHandler<T> {
void onEach(List<T> each);
}
}
But in my opinion it's complicated to iterate lists in every test.
Is there more elegant way to test classes implementing the same interface in JUnit4?
You can create a base test which can test anything of type List<T> plus an abstract method which creates such a list.
Then implement a test per list type which extends the base test. JUnit will run the test cases from the base class plus any that you define in the extension.
abstract class AbstractListTest<T> {
protected abstract List<T> createList();
#Test
public void testIsEmpty() {
List<T> list = createList();
assertTrue(list.isEmpty());
}
...more tests...
}
class QuickListTest extends AbstractListTest<QuickList> {
protected QuickList createList() {
return new QuickList();
}
}
JUnit won't run the abstract base class but it will see the inherited tests and run all of them. You can also add new tests to QuickListTest or override ones from the base class.
Basically, JUnit will take the class, find all public #Test methods from the whole inheritance tree and run them.
I will consider breaking up the tests for different list implementations into their respective test cases, so that they pass or fail independently.
Using your .isEmpty() as an example, if QuickList.isEmpty() and EfficientMemoryList.isEmpty() have different implementations i.e. different meaning for the concept of empty, then it makes sense for them to be tested independently. Currently, your testIsEmptyAfterCreationEmptyList will fail if 1 list implementation failed, but the others passed.
Otherwise, if QuickList.isEmpty() and EfficientMemoryList.isEmpty() share the same implementation, then you can consider moving the implementation to a common base class, and write tests for that base class.
Just because classes share the same interface, doesn't mean their tests need to be lumped and coupled.
Create a test each implementation separatelly: QuickListTest and EfficientMemoryListTest.
QuickListTest.java
public class QuickListTest extends ListBase {
#Test
public void shouldBeEmpty() throws Exception {
assertThatIsEmpty(new QuickList<Integer>());
}
}
BaseList.java
public abstract class ListBase {
protected void assertThatIsEmpty(QuickList<Integer> actual) {
assertThat(actual).isEmpty();
}
}

Modulation of adding new Strings -> Method calls

If I have a program that does the following:
if(input=='abc'){do x}
if(input=='def'){do y}
In the future, I may want to add another piece of code like so:
if(input=='ghy'){do x}
As you can see, I am adding a new 'if' statement for a different conditional BUT using the SAME function X.
The code in future has potential to have lots of different IF statements (or switches) all of which are comparing a string vs a string and then performing a function. Considering the future expansion, I was wondering if there is a possible 'neater', 'modular' way of achieving the same results.
It's a shame I can't combine the String with a Method call in a hashtable (String, method) in Java. That way I could just store any new procedures inside a hashtable and grab the relevant method for that String.
Any ideas?
Thank you
EDIT: Thank you for everyone's solutions. I was surprised by the quantity and quality of replies I received in such a small amount of time.
Maybe you can use enum. Example:
public enum InputType
{
abc, def
{
#Override
public void x()
{
System.out.println("Another method");
}
},
ghy;
public void x()
{
System.out.println("One method");
}
}
And further:
InputType.valueOf("abc").x();
Cheers!
I guess you could always use a Map<String, Runnable> and map to anonymous Runnable implementations:
myMap.put("abc", new Runnable() { public void run() { do x } });
...
myMap.get(input).run();
You should take a look at the command pattern. There are several ways of implementing it, and frameworks such as Spring can help you do with in a clean way.
But in a simple manner here's what you could do:
1-Create a Command interface with a method that your program will have to call to do the task, say doTask()
2-Create classes for command X and Y, implementing the Command interface.
3-Create a Map<String, Command> that will map your commands (X and Y) to logical names
4-Create a configuration file of your choice, say a .properties file that will map your input to your command names: abc=X, def=Y, ghi=X
5-Your program then does lookups on the config file to know which command to run according to the input.
A lot of ifs always tell us that we could do this better. In your case better option is to use design pattern e.g. Chain of responsibility. You will have good implementation which you can dynamic change and your code will be easier to maintenance than ifs implementation.
Take a look at this adaptation chain of responsibility to your case:
Main:
public static void main(String[] args) {
ClassA classA = new ClassA(Arrays.asList("abc", "ghi"));
ClassB classB = new ClassB(Arrays.asList("def"));
classA.setNextInChain(classB); // you can always write Builder to do this
String input = "def";
classA.execute(input);
}
BaseClass:
public abstract class BaseClass {
private Collection<String> patterns = Collections.EMPTY_LIST;
protected BaseClass nextInChain;
protected abstract void doMethod(); // your doA, doB methods
public void execute(String input) {
// this replace many ifs in your previous implementation
if (patterns.contains(input)) {
doMethod();
} else {
nextInChain.execute(input);
}
}
public void setPatterns(Collection<String> patterns) {
this.patterns = patterns;
}
public void setNextInChain(BaseClass nextInChain) {
this.nextInChain = nextInChain;
}
}
Class in chain:
public class ClassA extends BaseClass {
ClassA(Collection<String> patterns) {
setPatterns(patterns);
}
#Override
protected void doMethod() {
// do A
}
}
public class ClassB extends BaseClass {...}

Categories

Resources