When writing test cases for end-to-end test scenarios using java, selenium, java; we can keep common steps into the base class method and specific add, edit steps in the specific class.
public abstract class XXXXBaseTest extends SeleniumTest {
#Test
public void validateCalendarUi() throws IOException {
**ExpCalendar expCalendar = openExpCalendar();**
String calenderAvailable = expCalendar.getHeaderViewText();
Assert.assertEquals(calenderAvailable, "Calendar View", "Failed : Calendar is not available");
}
}
Then, opened calendar() method is overridden in each specific class with specific steps.
public class XXXXXViewExpirationCalendarTest extends RefDataExpirationCalendarTest {
#Override
protected ExpCalendar openExpCalendar() {
//Here write specific methods
}
}
Is this appropriate approach for test scripting? Can we use inheritance concept to write test cases in this way?
Related
I do have a service which needs to handle two types of meal.
#Service
class MealService {
private final List<MealStrategy> strategies;
MealService(…) {
this.strategies = strategies;
}
void handle() {
var foo = …;
var bar = …;
strategies.forEach(s -> s.remove(foo, bar));
}
}
There are two strategies, ‘BurgerStrategy’ and ‘PastaStrategy’. Both implements Strategy interface with one method called remove which takes two parameters.
BurgerStrategy class retrieves meals of enum type burger from the database and iterate over them and perform some operations. Similar stuff does the PastaStrategy.
The question is, does it make sense to call it Strategy and implement it this way or not?
Also, how to handle duplications of the code in those two services, let’s say both share the same private methods. Does it make sense to create a Helper class or something?
does it make sense to call it Strategy and implement it this way or not
I think these classes ‘BurgerStrategy’ and ‘PastaStrategy’ have common behaviour. Strategy pattern is used when you want to inject one strategy and use it. However, you are iterating through all behaviors. You did not set behaviour by getting one strategy and stick with it. So, in my honour opinion, I think it is better to avoid Strategy word here.
So strategy pattern would look like this. I am sorry, I am not Java guy. Let me show via C#. But I've provided comments of how code could look in Java.
This is our abstraction of strategy:
public interface ISoundBehaviour
{
void Make();
}
and its concrete implementation:
public class DogSound : ISoundBehaviour // implements in Java
{
public void Make()
{
Console.WriteLine("Woof");
}
}
public class CatSound : ISoundBehaviour
{
public void Make()
{
Console.WriteLine("Meow");
}
}
And then we stick with one behaviour that can also be replaced:
public class Dog
{
ISoundBehaviour _soundBehaviour;
public Dog(ISoundBehaviour soundBehaviour)
{
_soundBehaviour = soundBehaviour;
}
public void Bark()
{
_soundBehaviour.Make();
}
public void SetAnotherSound(ISoundBehaviour anotherSoundBehaviour)
{
_soundBehaviour = anotherSoundBehaviour;
}
}
how to handle duplications of the code in those two services, let’s say both share the same private methods.
You can create one base, abstract class. So basic idea is to put common logic into some base common class. Then we should create abstract method in abstract class. Why? By doing this, subclasses will have particular logic for concrete case. Let me show an example.
An abstract class which has common behaviour:
public abstract class BaseMeal
{
// I am not Java guy, but if I am not mistaken, in Java,
// if you do not want method to be overriden, you shoud use `final` keyword
public void CommonBehaviourHere()
{
// put here code that can be shared among subclasses to avoid code duplication
}
public abstract void UnCommonBehaviourShouldBeImplementedBySubclass();
}
And its concrete implementations:
public class BurgerSubclass : BaseMeal // extends in Java
{
public override void UnCommonBehaviourShouldBeImplementedBySubclass()
{
throw new NotImplementedException();
}
}
public class PastaSubclass : BaseMeal // extends in Java
{
public override void UnCommonBehaviourShouldBeImplementedBySubclass()
{
throw new NotImplementedException();
}
}
I would like to get a list of test methods from the current test class before it is started. When I tried to extend TestListenerAdapter for this, testContext.getAllTestMethods() returned all test methods from all classes. But how to get only methods from the current class?
I found a partial answer on the question. First of all, I can get all test methods by extending TestListenerAdapter
public class MyListener extends TestListenerAdapter {
#Override
public void onStart(ITestContext testContext) {
super.onStart(testContext);
ITestNGMethod[] methods = testContext.getAllTestMethods();
// here we can save methods into some object
}
Then, in our test class in #BeforeClass() we can access the object and get the only methods from the this.getClass().getName() class. So, we filter the only methods from the current class. In this case we can access all required information like description and other important test attributes.
If you don't have a listener, you can also use the #BeforeClass annotation similar way as specified by OP's own answer:
#BeforeClass
public void setup(ITestContext context) {
for (ITestNGMethod method : context.getAllTestMethods()) {
if(method.getRealClass() == this.getClass()) {
// do what you have to do
}
}
}
What is the best way to write junit tests for interfaces so they can be used for the concrete implementing classes?
e.g. You have this interface and implementing classes:
public interface MyInterface {
/** Return the given value. */
public boolean myMethod(boolean retVal);
}
public class MyClass1 implements MyInterface {
public boolean myMethod(boolean retVal) {
return retVal;
}
}
public class MyClass2 implements MyInterface {
public boolean myMethod(boolean retVal) {
return retVal;
}
}
How would you write a test against the interface so you can use it for the class?
Possibility 1:
public abstract class MyInterfaceTest {
public abstract MyInterface createInstance();
#Test
public final void testMyMethod_True() {
MyInterface instance = createInstance();
assertTrue(instance.myMethod(true));
}
#Test
public final void testMyMethod_False() {
MyInterface instance = createInstance();
assertFalse(instance.myMethod(false));
}
}
public class MyClass1Test extends MyInterfaceTest {
public MyInterface createInstance() {
return new MyClass1();
}
}
public class MyClass2Test extends MyInterfaceTest {
public MyInterface createInstance() {
return new MyClass2();
}
}
Pro:
Need only one method to be implemented
Con:
Dependencies and mock objects of class under test have to be the same for all tests
Possibility 2:
public abstract class MyInterfaceTest
public void testMyMethod_True(MyInterface instance) {
assertTrue(instance.myMethod(true));
}
public void testMyMethod_False(MyInterface instance) {
assertFalse(instance.myMethod(false));
}
}
public class MyClass1Test extends MyInterfaceTest {
#Test
public void testMyMethod_True() {
MyClass1 instance = new MyClass1();
super.testMyMethod_True(instance);
}
#Test
public void testMyMethod_False() {
MyClass1 instance = new MyClass1();
super.testMyMethod_False(instance);
}
}
public class MyClass2Test extends MyInterfaceTest {
#Test
public void testMyMethod_True() {
MyClass1 instance = new MyClass2();
super.testMyMethod_True(instance);
}
#Test
public void testMyMethod_False() {
MyClass1 instance = new MyClass2();
super.testMyMethod_False(instance);
}
}
Pro:
fine granualtion for each test including dependencies and mock objects
Con:
Each implementing test class requires to write additional test methods
Which possibility would you prefer or what other way do you use?
Contrary to the much-voted-up answer that #dlev gave, it can sometimes be very useful/needful to write a test like you're suggesting. The public API of a class, as expressed through its interface, is the most important thing to test. That being said, I would use neither of the approaches you mentioned, but a Parameterized test instead, where the parameters are the implementations to be tested:
#RunWith(Parameterized.class)
public class InterfaceTesting {
public MyInterface myInterface;
public InterfaceTesting(MyInterface myInterface) {
this.myInterface = myInterface;
}
#Test
public final void testMyMethod_True() {
assertTrue(myInterface.myMethod(true));
}
#Test
public final void testMyMethod_False() {
assertFalse(myInterface.myMethod(false));
}
#Parameterized.Parameters
public static Collection<Object[]> instancesToTest() {
return Arrays.asList(
new Object[]{new MyClass1()},
new Object[]{new MyClass2()}
);
}
}
I strongly disagree with #dlev. Very often it is a very good practice writing tests that use interfaces. Interface defines contract between client and the implementation. Very often all your implementations must pass exactly the same tests. Obviously each implementation can have its own tests.
So, I know 2 solutions.
Implement abstract test case with various tests that use interface. Declare abstract protected method that returns concrete instance. Now inherit this abstract class as many times as you need for each implementation of your interface and implement the mentioned factory method accordingly. You can add more specific tests here as well.
Use test suites.
I disagree with dlev as well, there's nothing wrong with writing your tests against interfaces instead of concrete implementations.
You probably want to use parameterized tests. Here is what it would look like with TestNG, it's a little more contrived with JUnit (since you can't pass parameters directly to test functions):
#DataProvider
public Object[][] dp() {
return new Object[][] {
new Object[] { new MyImpl1() },
new Object[] { new MyImpl2() },
}
}
#Test(dataProvider = "dp")
public void f(MyInterface itf) {
// will be called, with a different implementation each time
}
Late addition to the subject, sharing newer solution insights
I'm also looking for a proper and efficient way of testing (based on JUnit) correctness of multiple implementations of some interfaces and abstract classes. Unfortunately, neither JUnit's #Parameterized tests nor TestNG's equivalent concept correctly fits my requirements, since I don't know a priori the list of implementations of these interface/abstract classes that might exists. That is, new implementations might be developped, and testers might not have access to all existing implementations; it is therefore not efficient to have test classes specify the list of implementation classes.
At this point, I have found the following project which seems to offer a complete and efficient solution to simplify this type of tests: https://github.com/Claudenw/junit-contracts . It basically allows the definition of "Contract Tests", through the annotation #Contract(InterfaceClass.class) on contract test classes. Then an implementer would create an implementation specific test class, with annotations #RunWith(ContractSuite.class) and #ContractImpl(value = ImplementationClass.class); the engine shall automatically apply any contract test that applies to ImplementationClass, by looking for all Contract Test defined for any interface or abstract class from which ImplementationClass derives. I have not yet tested this solution, but this sounds promising.
I have also found the following library: http://www.jqno.nl/equalsverifier/ . This one satisfies a similar though much more specific need, which is asserting a class conformity specifically to Object.equals and Object.hashcode contracts.
Similarly, https://bitbucket.org/chas678/testhelpers/src demonstrate a strategy to validate some Java fondamental contracts, including Object.equals, Object.hashcode, Comparable.compare, Serializable. This project use simple test structures, which, I believe, can be easily reproduced to suite any specific needs.
Well, that's it for now; I'll keep this post updated with other usefull informations I may find.
I would generally avoid writing unit tests against an interface, for the simple reason that an interface, however much you would like it to, does not define functionality. It encumbers its implementors with syntactic requirements, but that's it.
Unit tests, conversely, are intended to ensure that the functionality you expect is present in a given code path.
That being said, there are situations where this type of test could make sense. Assuming you wanted these tests to ensure that classes you wrote (that share a given interface) do, in fact, share the same functionality, then I would prefer your first option. It makes it easiest on the implementing subclasses to inject themselves into the testing process. Also, I don't think your "con" is really true. There's no reason you can't have the classes actually under test provide their own mocks (though I think that if you really need different mocks, then that suggests your interface tests aren't uniform anyway.)
with java 8 i do this
public interface MyInterfaceTest {
public MyInterface createInstance();
#Test
default void testMyMethod_True() {
MyInterface instance = createInstance();
assertTrue(instance.myMethod(true));
}
#Test
default void testMyMethod_False() {
MyInterface instance = createInstance();
assertFalse(instance.myMethod(false));
}
}
public class MyClass1Test implements MyInterfaceTest {
public MyInterface createInstance() {
return new MyClass1();
}
}
public class MyClass2Test implements MyInterfaceTest {
public MyInterface createInstance() {
return new MyClass2();
}
#Disabled
#Override
#Test
public void testMyMethod_True() {
MyInterfaceTest.super.testMyMethod_True();
};
}
Let's say I have the following TestNG test class:
public class OwnTestLauncher {
#Test(dataProvider = "valid-provider")
public void validSintax(Collection<File> files) throws PlooException {
runFilesThroughCompiler(files);
}
#Test(dataProvider = "invalid-provider")
public void invalidSintax(Collection<File> files) throws PlooException {
runFilesThroughCompiler(files);
}
protected String someAlgoritmUsedByRunFilesThroughCompiler(...) { ... }
...
}
And I'd like to then create some slightly different suits, so I can run each one of them on different ocasions:
public class SomeOtherFlavour extends OwnTestLauncher {
#Override
protected String someAlgoritmUsedByRunFilesThroughCompiler(files) { ... }
}
I've tried run the code shown above but it didn't work. I've also tried to annotate SomeOtherFlavour with #Test but that didn't seem to help. Is it possible, at all, to do what I'm trying to do?
I'm afraid you have to extract the someAlgoritmUsedByRunFilesThroughCompiler into a separate interface (or abstract class), and write different implementation classes of it.
public interface MyAlgorithm {
String someAlgoritmUsedByRunFilesThroughCompiler(...);
}
The test methods in OwnTestLauncher then expect an implementation of this interface as an additional parameter, and you can still use your data providers by adapting them.
Imagine you have an application and you want to make unit tests and functionnal tests over it (not quite hard to imagine). You might have an abstract class, let's call it AbstractTestClass, from which all your unit tests extends.
AbstractTestClass would look something like this (using JUnit 4) :
class AbstractTestClass {
boolean setupDone = false;
#Before
public void before() {
if(!setupDone) {
// insert data in db
setupDone = true;
}
}
}
Here is what I'm struggling with. I'm having another abstract class which test the web interfaces :
class AbstractWebTestClass extends WebTestCase {
boolean setupDone = false;
#Before
public void before() {
if(!setupDone) {
// here, make a call to AbstractTestClass.before()
// init the interfaces
setupDone = true;
}
// do some more thing
}
}
It's pretty much the same class, except that it extends WebTestCase. This design could give me the possibility to have the same data while unit testing than when testing the interface.
Usually, when dealing with such issue, you should favor composition over inheritance or use a strategy pattern.
Unfortunately, I don't quite like the idea to favor composition over inheritance in this particular scenario and I don't see how I could use a strategy pattern, there is probably a design flaw and I can't quite see the solution.
How could I design this architecture in order to achieve my goal.
I would implement this in the following way:
class Example {
class LazyInitStrategy implements Runnable {
private final Runnable operation;
private boolean done = false;
LazyInitStrategy(Runnable operation) {
this.operation = operation;
}
#Override
public void run() {
if (!done) {
operation.run();
done = true;
}
}
}
private final class AbstractInit implements Runnable {
public void run() {
// insert data in db
}
}
private final class AbstractWebInit implements Runnable {
public void run() {
// here, make a call to AbstractTestClass.before() init the interfaces
}
}
class AbstractTestClass {
final LazyInitStrategy setup = new LazyInitStrategy(new AbstractInit());
#Before
public void before() {
setup.run();
// do some more thing
}
}
class AbstractWebTestClass extends WebTestCase {
final LazyInitStrategy setupInfo = new LazyInitStrategy(new AbstractWebInit());
#Before
public void before() {
setupInfo.run();
// do some more thing
}
}
}
Sure this is very simplistic solution but it should eliminate if/else logic duplication for checking if setup was done. Using Runnable is optional, I did this just for demo purposes, in read world you probably will use another interface.
The important thing to accomplish is not to duplicate code. In this situation I would create a
MyScenarioTestUtil
class that has a bunch of static methods on it that sets up the data as you need to. You would invoke the utility methods from the setup. That way you keep all the code in one place.
Its really just a semantics difference from using composition...
I think that the design is wrong in general. You shouldn't use inheritance in unit tests at all. Tests should be isolated and really plain. Very often, like in your case, it's necessary to prepare some supplementary objects, that will help test methods to do their job. In such a case you should define builders of such objects, and place them somewhere outside of test cases.
For example:
public void testMethodThatNeedsSomePreparedObjects() {
Foo foo = new FooBuilder()
.withFile("some-text.txt")
.withNumber(123)
.build();
// now we are testing class Bar, using object of class Foo
Bar bar = new Bar(foo);
}
Thus, you need FooBuilder to be defined somewhere else, and this class will do all the work you're now trying to do using stategy pattern or inheritance. Both approached are wrong, when dealing with unit tests.