How to create a template class file in java - java

I am creating a test automation framework using selenium & TestNG. This Framework will be use by all of the other team member. Want to specify a class template for all the team member so that basic structure of the test class will same for all and reduce the effort for writing the same structure for all test.
Whenever any member create any class in a particular package the class will be created with some predefined code like below
package com.xxx.yyy.testmodule.dummytest;
import org.testng.annotations.Test;
import com.xxx.yyy.lib.zzz.CommonLib;
public class Test3 extends CommonUtilCommonLibities{
#Test(description="", groups= {""})
public void testTest3() {
//Read Test Data Here
//Test Logic
//Test Verification
}
}

Use an abstract class :
package com.xxx.yyy.testmodule.dummytest;
import org.testng.annotations.Test;
import com.xxx.yyy.lib.zzz.CommonLib;
public abstract class Test3 extends CommonUtilCommonLibities {
#Test(description="", groups= {""})
public void testTest3() {
//Read Test Data Here
Data data = readTestData();
//Test Logic
test(data);
//Test Verification
testAssertion(data);
}
abstract Data readTestData();
abstract void test(Data data);
abstract void testAssertion(data);
}
Of course this only works if all your data beans extend some base bean which is Data in my example.

If you use Intellij IDEA, you can define a test class template, including your methods. There's a similar question with the instructions.
You may also want to make use of a Template Method pattern:
public abstract class GenericTest<T> {
#Test
public void doTest() {
T data = loadTestData();
this.runTestLogic(data);
this.runAssertions(data);
// something else...
}
protected abstract T loadTestData();
protected abstract void runTestLogic(T result);
protected abstract void runAssertions(T result);
}
Your concrete test classes will extend this generic class and implement the actual testing and data reading logic:
public class ConcreteTest extends GenericTest<Integer> {
#Override
protected Integer loadTestData() {
return 42;
}
#Override
protected void runTestLogic(Integer result) {
System.out.println(result);
}
#Override
protected void runAssertions(Integer result) {
assertEquals(0, result % 2);
}
}

Related

Inheritace common test steps from base class

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?

Java: How to get the object of a subclass by calling it's parent class

import java.util.*;
import java.lang.*;
import java.io.*;
class mainA {
private mainA obj;
public mainA(int type) {
System.out.println("accessing mainA");
switch(type) {
case 1:
obj = new mysql();
break;
case 2:
obj = new mssql();
break;
default:
break;
}
}
}
class mysql extends mainA {
public void printme() {
System.out.println("accessing mysql");
}
}
class mssql extends mainA {
public void printme() {
System.out.println("accessing mssql");
}
}
class C2 extends mainA {
public C2() {
super();
}
public static void main(String args[]){
Object b = new C2();
b.printme();
}
}
I need to achieve the following scenario. It would be great if someone can help me out.
I'm trying to create a common API library set which can be scaled to as many backend databases as possible.
The idea is to create an object of C2, which in turn would return the value of either mysql/mssql based on the dbtype. The type parameter can be obtained from any where in the code. mainA is the super class which consists of config params. Type can be obtained here as well. The problem here is that I'm stuck with not being able to get the object of mysql/mssql from C2. The ideal situation would be to create an object of C2 which refers to mainA that gets the type and inits either mssql/mysql. C2.printme must call the db class which was specified in the type.
Would generic classes be of any help here?
you can have an instanceof test to cast the object but it is lame as you would have to change your code if you are adding a new type of DB object.
You can have a good interface and make the subclasses implement it so that you can call through your interface without caring about the actual implementation object.
Coding to Interface is what you should be doing.
You've got some work ahead of you. You'll want to read up on interfaces. In your example, you can do something like the following (it's a bit silly in the real world).
Let's call our interface Printable.java (by convention, starts with either the capital letter "I" or ends in "-ible", "able," etc). I wouldn't really call it Printable, but for the purpose of this example:
public interface Printable {
public void logDatabaseType();
}
Your parent class (we can make it abstract so that it cannot be created directly without an underlying implementation):
public abstract class Database implements Printable {
#Override
public void logDatabaseType() {
System.out.println("logDatabaseType()");
}
}
Your subclasses:
public class MySQL extends Database implements Printable {
#Override
public void logDatabaseType() {
System.out.println("Accessing MySQL");
}
}
public class MicrosoftSQL extends Database implements Printable {
#Override
public void logDatabaseType() {
System.out.println("Accessing MSSQL");
}
}
In your test class (you should try to get your feet wet with JUnit as early as possible):
public class DatabaseLogTest {
#Test
public void printDatabaseType() {
//programming by interface
Printable printable = new MySql();
printable.logDatabaseType();
printable = new MicrosoftSQL();
printable.logDatabaseType();
//then later you can do
//someMethod(printable);
//and the printable object will retain whatever was instantiated
//and someMethod will be blissfully ignorant of the actual implementation
}
}
#Override is important because it tells your IDE and the developer that you're overriding an implementation and the IDE will spit out errors if the implied contract is not met. You should have this whenever you're overriding.
You'd also want to use a logger (e.g., SLF4j over Log4J or logback) rather than System.out.println() method calls.

How to check if class has methods added by aspect?

Suppose I have a simple class:
public class TestClass {
/*...*/
}
I created an aspect which injects new method to this class:
public aspect TestAspect {
public void TestClass.aspectMethod() {
/*...*/
}
}
Now, how can I check if TestClass has method added by TestAspect in runtime?
The simplest way would be to simply reflect on the class:
TestClass.class.getDeclaredMethod("aspectMethod")
which will throw NoSuchMethodException if it isn't there. Or if you have the bytes you could use a byte code visitor to check what methods exist in the byte code - but the reflective route would be less messing around.
Andy's answer is the correct one, I just want to answer your follow-up question from the comment:
Duck typing is not a Java feature, but if you use ITD in order to make the class implement an interface and then have an instance of your aspect-extended class you can use instanceof MyInterface in order to determine what you need to know. Other ways (also using reflection) are also available:
Interface with the method you want to add later via ITD:
package de.scrum_master.app;
public interface MyInterface {
void myMethod();
}
Sample driver application:
package de.scrum_master.app;
import java.lang.reflect.Type;
public class Application {
public static void main(String[] args) {
Application application = new Application();
// Use an instance
System.out.println(application instanceof MyInterface);
System.out.println(MyInterface.class.isInstance(application));
// Use the class
for (Type type : Application.class.getGenericInterfaces())
System.out.println(type);
for (Class<?> clazz : Application.class.getInterfaces())
System.out.println(clazz);
}
}
Aspect:
package de.scrum_master.aspect;
import de.scrum_master.app.Application;
import de.scrum_master.app.MyInterface;
public aspect MyAspect {
declare parents : Application implements MyInterface;
public void Application.myMethod() {}
}
Application output:
true
true
interface de.scrum_master.app.MyInterface
interface de.scrum_master.app.MyInterface

Strange behaviour on method annotations and default access level

Here's my problem...
I have an annotation in package pkg3:
package pkg3;
import java.lang.annotation.*;
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface TestAnno {
}
Also I have two classes in package pkg1, one with public access and one with default access
package pkg1;
import pkg3.TestAnno;
class Class1 {
#TestAnno
public void test1() { }
public void test2() { }
}
and
package pkg1;
import pkg3.TestAnno;
public class Class2 extends Class1 {
#TestAnno
public void test3() { }
public void test4() { }
}
Finnally I've got a main class in package pkg2
package pkg2;
import java.lang.reflect.Method;
import pkg1.Class2;
import pkg3.TestAnno;
public class MainClass {
public static void main(String[] args) {
Class2 cls = new Class2();
for(Method m: cls.getClass().getMethods()) {
System.out.println(m);
if (m.getAnnotation(TestAnno.class) != null) {
System.out.println(" > hass anno");
}
}
}
}
Running this example I expect to see the info, that two methods have #TestAnno present - test1 and test3, but I only see one test3, and... what is strange, the methods test1 and test2 are listed as they were be declared in class Class2.
public void pkg1.Class2.test3()
> hass anno
public void pkg1.Class2.test4()
public void pkg1.Class2.test1()
public void pkg1.Class2.test2()
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
... rest methods from java.lang.Object
I know, that getMethods returns only public methods from given glass (and it's all super classes) but... this is strange for me.
I'm using this in order to separate generated classes (which have default access) from implementation classes (which are public and they're extending generated classes).
Have I to use public access in generated classes (I wanted them not to be visible to rest of the world) or is there any way to get annotated public methods from Class1 ?
This answer is just a "one big maybe" made by a man at 3 a.m. so it will require JLS confrontation, better terminology and more informations. I was planning to post it as comment but unfortunately it is too long :/
Lets take a look at this classes
class SomeClass {
#TestAnno
public void test(){}
}
class SomeDefaultClass extends SomeClass {
}
public class SomePublicClass extends SomeClass {
}
now take a look at this code and its result
Method m1 = SomePublicClass.class.getMethod("test");
Method m2 = SomeDefaultClass.class.getMethod("test");
System.out.println(m1 + "\t> " + m1.getAnnotation(TestAnno.class));
System.out.println(m2 + "\t\t> " + m2.getAnnotation(TestAnno.class));
output
public void SomePublicClass.test() > null
public void SomeClass.test() > #TestAnno()
As you see public class that extends class with package modifier doesn't inherit annotations, but class with package modifier does.
Why is that?
Both SomeDefaultClass and SomePublicClass "inherited" test() method but not in the same way.
If you take a look at result of javap SomeDefaultClass.class you will see
class SomeDefaultClass extends SomeClass {
SomeDefaultClass();
}
so it doesn't have test() method in its binaries, so it will use it from SomeClass which have TestAnno annotation.
On the other hand if you take a look at result of javap SomePublicClass you will see
public class SomePublicClass extends SomeClass {
public SomePublicClass();
public void test();
}
which means that code of test() method has been overridden in SomePublicClass so this method has been declared again in SomePublicClass but unfortunately without previous annotations and since overridden method doesn't have annotations you wont see them in your code. (Why annotations are not added when compiler is overriding method? Honestly, I don't know :/)
Why is overriding happening? I suspect that since SomePublicClass is public and test is also public it should be accessible from all packages, but since SomeClass has default/package visibility this method couldn't be accessible via SomeClass from outside of its package.
To prevent moving/copying test method from one class to another you can make both classes public or default/package.

Possible to use inheritance in TestNG test suits?

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.

Categories