What we're starting with
I have a main test listener, which just set up the web driver on set up, and free the resource on teardown:
import org.openqa.selenium.WebDriver
import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.chrome.ChromeOptions
import com.kms.katalon.core.annotation.AfterTestCase
import com.kms.katalon.core.annotation.BeforeTestCase
import com.kms.katalon.core.context.TestCaseContext
import com.kms.katalon.core.webui.driver.DriverFactory
import internal.GlobalVariable
class NewTestListener {
private WebDriver driver;
/**
* Executes before every test case starts.
* #param testCaseContext related information of the executed test case.
*/
#BeforeTestCase
def sampleBeforeTestCase(TestCaseContext testCaseContext) {
String pathToChromeDriver = System.getProperty("user.home") + GlobalVariable.pathToKatalon + '\\configuration\\resources\\drivers\\chromedriver_win32\\chromedriver.exe'
System.setProperty('webdriver.chrome.driver', pathToChromeDriver)
ChromeOptions chromeProfile = new ChromeOptions()
chromeProfile.addArguments('user-data-dir=' + System.getProperty("user.home") + GlobalVariable.pathToUserDataDir)
chromeProfile.addArguments('profile-directory=Default')
this.driver = new ChromeDriver(chromeProfile)
this.driver.manage().window().maximize()
this.driver.get('https://crm.zoho.com')
DriverFactory.changeWebDriver(this.driver)
}
#AfterTestCase
def sampleAfterTestCase(TestCaseContext testCaseContext) {
this.driver.quit()
}
}
What we're tryna do
I have dozens of test cases, that pertain to distinct pages, categorized under distinct folders, which I want to abstract out common set up,teardown concerns.
How do we want to do it
I try to create some BaseCategoryListener, which get implemented by the category of test:
import java.util.regex.Pattern
import com.kms.katalon.core.annotation.AfterTestCase
import com.kms.katalon.core.annotation.BeforeTestCase
import com.kms.katalon.core.context.TestCaseContext
abstract class BaseCategoryListener {
abstract List<Pattern> getCategory();
public void setup(TestCaseContext testCaseContext) {
}
public void teardown(TestCaseContext testCaseContext) {
}
boolean isInCategory(TestCaseContext testCaseContext) {
for (Pattern regex : this.getCategory()) {
if (regex.matcher(testCaseContext.getTestCaseId()).matches()) return true;
}
return false;
}
/**
* Executes before every test case starts.
* #param testCaseContext related information of the executed test case.
*/
#BeforeTestCase
def sampleBeforeTestCase(TestCaseContext testCaseContext) {
if (this.isInCategory(testCaseContext)) {
this.setup(testCaseContext)
}
}
/**
* Executes after every test case ends.
* #param testCaseContext related information of the executed test case.
*/
#AfterTestCase
def sampleAfterTestCase(TestCaseContext testCaseContext) {
if (this.isInCategory(testCaseContext)) {
this.teardown(testCaseContext)
}
}
}
implement it like so:
import static com.kms.katalon.core.testobject.ObjectRepository.findTestObject
import java.util.regex.Pattern
import com.kms.katalon.core.context.TestCaseContext
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
class ContractTestsListener extends BaseCategoryListener{
#Override
public List<Pattern> getCategory() {
return [
~/Test Cases\/New Zoho\/Practice Contract\/.*/
]
}
#Override
public void setup(TestCaseContext testCaseContext) {
WebUI.navigateToUrl(testCaseContext.getTestCaseVariables()["initURL"])
WebUI.click(findTestObject('Page_Practice - Zoho CRM/Third Row Section/Contract Tab Pane/New Contract button'))
WebUI.waitForElementNotPresent(findTestObject('Page_Practice - Zoho CRM/Third Row Section/Contract Tab Pane/New Contract button'), 3)
WebUI.waitForPageLoad(5)
}
}
What happens when you try to use that:
When I pick a test case in the folder Test Cases/New Zoho/Practice Contract to remove the setup hook from (because it was already copied and pasted into the test listener), that test case now fails because the ContractTestsListener setup happens before the NewTestListener setup!
How can I control the flow of the test listener hooks in Katalon Studio?
Related
Currently practicing running TestNG tests on the Lord & Taylor online site and I have an issue where a overlaying pop up from Lord and Taylor pops up on the screen at least once during a session. Most of the time it appears on the Homepage but can also appear once I click on one of the sections. I have tried using the xpath but it seems to change every time I run the browser. I have also tried using link text but that doesnt seem to work either. I can use an Implicit wait and manually click out of it but I feel like there has to be a way to do this with code. I also run into a problem where sometimes the ad wont load at all so it allows me to complete the initial few tests before it pops up out of nowhere. Its become a hurdle for me that I cant seem to get over. Ive attached what my code looks like now and can really use some help figuring this out.
package com.LT.Tests;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.LT.Pages.googlePage;
import com.LT.Pages.homePage;
public class homepageTest {
WebDriver driver;
googlePage gp;
homePage hp;
#BeforeTest
public void beforeTest() throws InterruptedException {
System.setProperty("webdriver.chrome.driver","/Users/nezamseraj/Desktop/WSA/Drivers/chromedriver 5");
driver = new ChromeDriver();
hp = new homePage(driver);
gp = new googlePage(driver);
driver.manage().deleteAllCookies();
Thread.sleep(2000);
driver.get("https://www.google.com/");
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
}
#AfterTest
public void afterTest() {
driver.quit();
}
#Test
public void gpValidation() {
boolean searchbar = gp.searchBar().isEnabled();
boolean searchbutton = gp.searchbutton().isEnabled();
Assert.assertTrue(searchbar);
Assert.assertTrue(searchbutton);
}
#Test(priority = 2)
public void searchLT() {
gp.searchBar().sendKeys("Lord and Taylor");
gp.searchbutton().click();
gp.ltLink().click();
}
#Test(priority = 3)
public void dismissAD() {
WebDriverWait wait = new WebDriverWait(driver,30);
wait.until(ExpectedConditions.elementToBeClickable(By.linkText("DECLINE OFFER")));
hp.declineOffer().click();
}
#Test(priority = 3)
public void hpValidation() {
boolean ws = hp.womenSection().isEnabled();
boolean ds = hp.designerSection().isEnabled();
boolean as = hp.accessoriesSection().isEnabled();
Assert.assertTrue(ws);
Assert.assertTrue(ds);
Assert.assertTrue(as);
}
}
We are using QAF and utilizing qaf webdriver and webelement listeners for to deal with random popups.
You can add retry in element or driver listener's onfailure method. Ideal example is unexpected or random popup that needs to be dismissed. The implementation may look like below:
public void onFailure(QAFExtendedWebElement element, CommandTracker commandTracker) {
//check and close popup if exist
boolean shouldRetry = closePopUpIfExist();
if (commandTracker.hasException()
&& commandTracker.getException() instanceof StaleElementReferenceException) {
element.setId("-1");
shouldRetry = true;
}
commandTracker.setRetry(shouldRetry);
}
closePopUpIfExist implementation may look like below:
private void closePopUpIfExist(){
QAFExtendedWebElement popup_declineEle = new QAFExtendedWebElement("link=DECLINE OFFER");
if(popup_declineEle.isPresent() && popup_declineEle.isDisplayed()){
popup_declineEle.click();
return true;
}
return false;
}
UPDATE:
With qaf take benefit of base test class and base test page
public class homepageTest extends extends WebDriverTestCase {
#Test
public void gpValidation() {
GooglePage gp = new GooglePage();
gp.launchPage(null);
gp.getSearchTextbox().verifyEnabled();
gp.searchbutton().verifyEnabled();
// this test case doesn't makes sense because google is not your AUT and here you are testing google functionality!...
}
#Test(priority = 3)
public void hpValidation() {
GooglePage gp = new GooglePage();
gp.launchPage(null);
gp.getSearchTextbox().sendKeys("Lord and Taylor");
gp.searchbutton().click();
gp.ltLink().click();
HomePage hp = new HomePage();
hp.womenSection().verifyEnabled();
hp.designerSection().verifyEnabled();
hp.accessoriesSection().verifyEnabled();
}
}
Your page class may look like below:
public class GooglePage extends WebDriverBaseTestPage<WebDriverTestPage>{
//declare elements
// you can use #Findby from selenium support or from qaf
#FindBy(locator = "name=q")
private QAFWebElement searchTextbox;
...
protected void openPage(PageLocator loc){
driver.get("https://www.google.com/");
}
public QAFWebElement getSearchTextbox(){
return searchTextbox;
}
...
}
public class HomePage extends WebDriverBaseTestPage<WebDriverTestPage>{
//declare elements
// you can use #Findby from selenium support or from qaf
protected void openPage(PageLocator loc){
driver.get("/");
}
}
You may observe that there is no code to create/teardown driver. That is done through properties.
driver.name=chromeDriver
I would suggest checkout sample project. It has basic google search test case available with example configuration. you can download from github and run as maven test for playing around.
I've tried to modify minecraft by adding a new item called "uranium". Therefore I created the class "Trauma.java" in the main package and a few other classes listed below.
All packages and classes:
Package Explorer
Trauma.java
package main;
import items.ItemUranium;
import net.minecraft.item.Item;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.registry.GameRegistry;
import proxy.ServerProxy;
#Mod(modid = Trauma.MODID)
public class Trauma {
public static final String MODID = "Trauma";
#SidedProxy(clientSide = "proxy.ClientProxy", serverSide = "proxy.ServerProxy")
public static ServerProxy proxy;
public static ItemUranium uranium = new ItemUranium();
#EventHandler
public void preInit(FMLPreInitializationEvent event) {
GameRegistry.register(uranium);
}
#EventHandler
public void init(FMLInitializationEvent event) {
proxy.registerClientStuff();
}
#EventHandler
public void postInit(FMLPostInitializationEvent event) {
}
}
BasicItem.java
package items;
import net.minecraft.item.Item;
public class BasicItem extends Item {
public BasicItem(String name) {
setUnlocalizedName(name);
setRegistryName(name);
}
}
ItemUranium.java
package items;
public class ItemUranium extends BasicItem {
public ItemUranium() {
super("uranium");
}
}
ClientProxy.java
package proxy;
import items.BasicItem;
import main.Trauma;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
public class ClientProxy extends ServerProxy {
#Override
public void registerClientStuff () {
registerItemModel(Trauma.uranium);
}
public static void registerItemModel(BasicItem item) {
Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(item, 0, new ModelResourceLocation(Trauma.MODID + ":" + item.getRegistryName(), "inventory"));
}
}
ServerProxy.java
package proxy;
public class ServerProxy {
public void registerClientStuff() {}
}
uranium.json
{
"parent": "item/generated",
"textures": {
"layer0": "Trauma:items/uranium"
}
}
uranium.png
ingame
Also I don't know why the item in inventory isn't called uranium...
I spent two hours on fixing the problem and it didn't help so it would be really nice if somebody of you may help me.
Thanks :)
Don't use the Model Mesher:
The model mesher is Vanilla (Mojang) code and using it correctly has always been finicky and unreliable, failing if you called it too early and failing if you called it too late. So Forge added the ModelLoader class to resolve that problem.
Replace this line:
Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(...)
With this line:
ModelLoader.setCustomModelResourceLocation(...)
The ... contents are identical.
Second, depending on what version of Minecraft you're using, you should...:
Stop using GameRegistry.Register
Instead use the RegistryEvent.Register<T> events (where <T> will be <Block> to register blocks, <Item> to register items, etc)
Register your models in the ModelRegistryEvent and no where else.
This event is #SideOnly(CLIENT) and can be subscribed to in your client proxy, avoiding the need to forward references through your proxy class. Eg. I do it like this, where lines 197-199 is the most common scenario needed, where the array is populated during the item registration event. The rest of that method handles the custom state mappers and custom mesh definitions that are used by only a handful of items/blocks and not relevant here.
Include your Mod ID in your unlocalized name. The best way to do this would be setUnlocalizedName(getRegistryName().toString());
See also the Forge documentation on events.
I have made a very simple class to test for proper Junit test generating. The problem is that when I create a Junit test, it doesn't find my methods for some reason. I have tried with multiple very simple classes without success. I am starting to think I set up Junit for the project incorrectly. Here is my simple class I am trying to test:
package controller;
public class SampleProgram {
public int multiply(int x1, int x2){
return x1 * x2;
}
}
Here is what is generated when I create a Junit Test in Netbeans:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package controller;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
public class ProgramTest {
public ProgramTest() {
}
#BeforeClass
public static void setUpClass() {
}
#AfterClass
public static void tearDownClass() {
}
#Before
public void setUp() {
}
#After
public void tearDown() {
}
}
Any help as to why my method isn't being found and generating the test is much appreciated. I have not used Junit before and am completely lost. Thanks
EDIT
Here is a screenshot of my editor with a Junit test provided from Jose Martinez.
The imports are the defaults for when netbeans creates a Junit test.
Screenshot
If you are referring to Netbeans auto unit test creator functionality then... When you right click a class in Nebeans project tab and select Tools -> Create/Update Tests, a dialog box will pop up. In the Code Generation box, under Method Access Levels, select the Public radio button.
But usually this auto feature is just to get you started. You will have to get comfortable with creating your own tests. In this case a good unit test for multiply might look something like this.
#Test
public void testMultiply() {
System.out.println("testingMultiply");
SimpleProgram instance = new SimpleProgram();
int expected = 12;
int p1 = 3;
int p2 = 4;
int actual = instance.multiply(p1, p2);
assertEqual(expected, actual);
}
You should select the correct Code Generation items from the wizard.
For some reason in the testEmployee method I am getting weird error messages saying illegal character.
I've looked at the code but can't find anything syntactically wrong with it.
Any help would be great thanks!
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import ttp.Cache;
import ttp.DataException;
import ttp.EmployeeDAO;
import ttp.Employee;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
/**
*
* #author ericrea
*/
public class Tester {
public Tester() {
}
#BeforeClass
public static void setUpClass() throws Exception {
}
#AfterClass
public static void tearDownClass() throws Exception {
}
#Before
public void setUp() {
}
#After
public void tearDown() {
}
// TODO add test methods here.
// The methods must be annotated with annotation #Test. For example:
//
// #Test
// public void hello() {}
// /** Test the Skeleton BO/DAO */
// #Test
// public void TestSkeleton() throws Exception {
// Skeleton s = SkeletonDAO.getInstance().create(“skeleton1”);
// s.save();
//
// // since skeleton1 is in the Cache, this tests reading from the cache
// Skeleton s2 = SkeletonDAO.getInstance().read(“skeleton1”);
// assertSame(s, s2);
//
// // now clear the cache (you’d never do this in the real world)
// // then we can test reading from the database
// Cache.getInstance().clear();
// Skeleton s3 = SkeletonDAO.getInstance().read(“skeleton1”);
// assertEquals(s.getId(), s3.getId());
// //assertEquals(s.getSomething(), s3.getSomething());
//
// // keep testing more methods, BOs, and DAOs
// }//TestSkeleton
// //5. Right-click the file and run the file. You’ll see it test. It will obviously have errors
// //because Skeleton isn’t a real BO/DAO.
// //6. Note in the above code the “assertEquals” methods. That is how you test that two things are equals.
#Test
public void TestEmployee() throws DataException {
Employee e = EmployeeDAO.getInstance().create(“Employee1”);
e.save();
// since skeleton1 is in the Cache, this tests reading from the cache
Employee e2 = EmployeeDAO.getInstance().read(“Employee1”);
assertSame(e, e2);
// now clear the cache (you’d never do this in the real world)
// then we can test reading from the database
Cache.getInstance().clear();
Employee e3 = EmployeeDAO.getInstance().read(“Employee1”);
assertEquals(e.getId(), e3.getId());
assertEquals(e.getName1(), s]e3.getName1());
}
You seem to use 'fancy' quotes (“) instead of normal ones (")
PS If Matt is right, please do not use Word to edit your programs. There're lots of IDEs, but even Notepad would be easier.
The fragment
s]e3.getName1()
(last line) doesn't look right: remove the "s]" fragment.
Edit: You are also missing the closing parenthesis for the class at the end of the code.
We occasionally have bugs that appear once in every X runs. Before people check in stuff (where it is automatically JUnit'd), our devs need to pass JUnit locally via Eclipse.
Is there some convenient way (built in or high-quality Plugin) to make Eclipse run the same test X times and stop if there's a failure? An alternative to just clicking Run X times?
Note that I'm looking for something in the UI (e.g., right click and say "Run X times" instead of just "Run").
If the for loop works, then I agree with nos.
If you need to repeat the entire setup-test-teardown, then you can use a TestSuite:
Right-click on the package containing the test to repeat
Go to New and choose to create a JUnit test SUITE
Make sure that only the test you want to repeat is selected and click through to finish.
Edit the file to run it multiple times.
In the file you just find the
addTestSuite(YourTestClass.class)
line, and wrap that in a for loop.
I'm pretty sure that you can use addTest instead of addTestSuite to get it to only run one test from that class if you just want to repeat a single test method.
If you really want to run a test class until failure, you need your own runner.
#RunWith(RunUntilFailure.class)
public class YourClass {
// ....
}
which could be implemented as follows...
package com.example;
import org.junit.internal.runners.*;
import org.junit.runner.notification.*;
import org.junit.runner.*;
public class RunUntilFailure extends Runner {
private TestClassRunner runner;
public RunUntilFailure(Class<?> klass) throws InitializationError {
this.runner = new TestClassRunner(klass);
}
#Override
public Description getDescription() {
Description description = Description.createSuiteDescription("Run until failure");
description.addChild(runner.getDescription());
return description;
}
#Override
public void run(RunNotifier notifier) {
class L extends RunListener {
boolean fail = false;
public void testFailure(Failure failure) throws Exception { fail = true; }
}
L listener = new L();
notifier.addListener(listener);
while (!listener.fail) runner.run(notifier);
}
}
...releasing untested code, feeling TDD guilt :)
Based on #akuhn's answer, here is what I came up with - rather than running forever, this will run 50 times or until failure, whichever comes first.
package com.foo
import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.InitializationError;
public class RunManyTimesUntilFailure extends Runner {
private static final int MAX_RUN_COUNT = 50;
private BlockJUnit4ClassRunner runner;
#SuppressWarnings("unchecked")
public RunManyTimesUntilFailure(final Class testClass) throws InitializationError {
runner = new BlockJUnit4ClassRunner(testClass);
}
#Override
public Description getDescription() {
final Description description = Description.createSuiteDescription("Run many times until failure");
description.addChild(runner.getDescription());
return description;
}
#Override
public void run(final RunNotifier notifier) {
class L extends RunListener {
boolean shouldContinue = true;
int runCount = 0;
#Override
public void testFailure(#SuppressWarnings("unused") final Failure failure) throws Exception {
shouldContinue = false;
}
#Override
public void testFinished(#SuppressWarnings("unused") Description description) throws Exception {
runCount++;
shouldContinue = (shouldContinue && runCount < MAX_RUN_COUNT);
}
}
final L listener = new L();
notifier.addListener(listener);
while (listener.shouldContinue) {
runner.run(notifier);
}
}
}
I know it doesn't answer the question directly but if a test isn't passing every time it is run it is a test smell known as Erratic Test. There are several possible causes for this (from xUnit Test Patterns):
Interacting Tests
Interacting Test Suites
Lonely Test
Resource Leakage
Resource Optimism
Unrepeatable Test
Test Run War
Nondeterministic Test
The details of each of these is documented in Chapter 16 of xUnit Test Patterns.
Here is a post I wrote that shows several ways of running the tests repeatedly with code examples:
http://codehowtos.blogspot.com/2011/04/run-junit-test-repeatedly.html
You can use the #Parametrized runner, or use the special runner included in the post
There is also a reference to a #Retry implementation
I don't believe there's a built in way for junit to do exactly what you're asking for.
If multiple runs produce different result, you should have a unit test testing that case. Wich might be as simple as running a for loop in the relevant test cases.
It is possible to implement such an loop with TestRules (since JUnit 4.9)
A very simple implementation that runs every Test 10 times:
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
public class SimpleRepeatRule implements TestRule {
private static class SimpleRepeatStatement extends Statement {
private final Statement statement;
private SimpleRepeatStatement(Statement statement) {
this.statement = statement;
}
#Override
public void evaluate() throws Throwable {
for (int i = 0; i < 10; i++) {
statement.evaluate();
}
}
}
#Override
public Statement apply(Statement statement, Description description) {
return new SimpleRepeatStatement(statement);
}
}
usage:
public class Run10TimesTest {
#Rule
public SimpleRepeatRule repeatRule = new SimpleRepeatRule();
#Test
public void myTest(){...}
}
For a more useful implementation based on an annotation that define which test method has to been executed how often have a look at this blog:
http://www.codeaffine.com/2013/04/10/running-junit-tests-repeatedly-without-loops/