How to use before in cucumber - selenium

How can I use "before" to create the driver instance and launch Firefox in cucumber feature file.
I am familiar with background but never used before.

This example is taken from ToolsQA
Let’s do some easy and small example of Cucumber Hooks just to understand the concept.
Feature: Test Hooks
Scenario: This scenario is to test hooks functionality
Given this is the first step
When this is the second step
Then this is the third step
Step Definitions
package stepDefinition;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
public class Hooks_Steps {
#Given("^this is the first step$")
public void This_Is_The_First_Step(){
System.out.println("This is the first step");
}
#When("^this is the second step$")
public void This_Is_The_Second_Step(){
System.out.println("This is the second step");
}
#Then("^this is the third step$")
public void This_Is_The_Third_Step(){
System.out.println("This is the third step");
}
}
****Note***: There is no logic used in the step definitions. Just printing the step summary log.*
Now hooks come in the picture, in case of your scenario, you will like to initialize the driver here.
Hooks
package utilities;
import cucumber.api.java.After;
import cucumber.api.java.Before;
public class Hooks {
#Before
public void beforeScenario(){
System.out.println("This will run before the Scenario");
}
#After
public void afterScenario(){
System.out.println("This will run after the Scenario");
}
}
Make sure that the package import statement should be import cucumber.api.java.After; & import cucumber.api.java.Before;
Often people mistaken and import Junit Annotations, so be careful with this.
Output
Aparts from hooks, you can make use of other usefull annotations in Cucumber, please refer the tutorial on ToolsQA.com here.

Related

Why doesn't intellij suggest org.mockito.Mockito dependency when using verify()?

When creating a new test, I have issues importing mockito methods into the class.
The class looks like
#ExtendWith(SpringExtension.class)
#SpringBootTest(classes = MainSpringBootApplication.class)
class CoolServiceTest {
#Autowired
SomeService someService;
#Test
void testGetInstitutionsCache_ShouldNotSecondTime() {
assertEquals(someService.getName(), "bob");
verify(idsClientMock, times(1));
}
}
In the import menu of intellij I don't see the option to import org.mockito.Mockito which I know where the package resides.
Instead I get the option to add;
import static org.testcontainers.shaded.com.google.common.base.Verify.verify;
(obviously not what I want)
I can get around it by typing the full Mockito.verify and then adding an on-demand static import to tidy the code.
The package is definitely installed and available to use, but intellij won't pick it up automatically.

initializationError when running Junit test in static

I have been on a search recently for an answer to my question and I cannot seem to find it. I am trying to execute a simple test to run a JUnit test in static. When I try to execute the test I receive the following Failure.
java.lang.Exception: Method SimpleINt()should not be static.
I have JUnit 4 and hamcrest installed and pathsbuilt.
(I am still new to Selenium/Java so I am sure there is an easy explanation for this.)
package iMAP;
import org.junit.Test;
public class Test1 {
#Test
public static void SimpleINt ()
{
int i = 34;
System.out.println(i);
}
}
The JUnit documentation for #Test states:
The Test annotation tells JUnit that the public void method to which it is attached can be run as a test case. To run the method, JUnit first constructs a fresh instance of the class then invokes the annotated method. Any exceptions thrown by the test will be reported by JUnit as a failure.
So, what is implicitly said here: the expectation is that #Test is only used for non static methods.
Beyond that: don't use keywords because you can. Learn what they mean. And static is something that you rather avoid (instead of using it all over the place).
Junit Methods should not be static as much I read and study. Just delete Static and try this:
package iMAP;
import org.junit.Test;
public class Test1 {
#Test
public void SimpleINt ()
{
int i = 34;
System.out.println(i);
}
}

Component objects instead of page objects in selenium

One of the most popular patterns in testing based on selenium is page object. Unfortunately, we often need to duplicate code if we use it as is. Consider the following situation:
We use UI framework, with common component, say some fancy table
Table is quite complicated, has filtering, sorting, searching
The table is used on several pages in the app
Is there any existing infrastructure to create more granular component objects instead of page objects either in selenium or in a thrid party lbirary?. I mean, annotations, and related infrastructure?
Appium which is the mobile implementation of selenium webdriver has a concept of widgets which is an extension of pageobjects. There is a Widget class which allows one to search relative to an element including in a web browser. You can check this out in the appium source test section. Have a look in the package io.appium.java_client.pagefactory_tests.widgets. This supports the FindBy annotation and WebElement construct and the PageFactory initialization.
So instead of using
#FindBy(.......)
private WebElement myTable;
you can use
#FindBy(container of the table....)
private Table myTable;
Table class can now have all the relevant variables and methods.
Part of POM.xml
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-api</artifactId>
<version>2.53.1</version>
</dependency>
<dependency>
<groupId>io.appium</groupId>
<artifactId>java-client</artifactId>
<version>4.1.2</version>
</dependency>
Test Class --
import io.appium.java_client.pagefactory.AppiumFieldDecorator;
import org.junit.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.PageFactory;
public class WidgetBrowTest {
#Test
public void test() {
System.setProperty("webdriver.chrome.driver", "E:/Software Testing/Selenium/Jars/chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("http://stackoverflow.com/");
SOHome soHome = new SOHome(driver);
PageFactory.initElements(new AppiumFieldDecorator(driver), soHome);
//Below two are from widget - First question in stackoverflow homepage
System.out.println(soHome.getFirstQues().getQuesTitle());
System.out.println(soHome.getFirstQues().getQuesTags());
//Below two are from home page
System.out.println(soHome.getLogoText());
System.out.println(soHome.getMenuText());
}
}
StackOverflow Home -
import java.util.List;
import java.util.stream.Collectors;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
public class SOHome {
#FindBy(css="div[id='hlogo'] > a")
private WebElement logo;
#FindBy(xpath="//div[#id='hmenus']//li/a")
private List<WebElement> menuOpt;
#FindBy(css="div[class='summary']")
private SOQuesWidget firstQues;
private WebDriver driver;
public SOHome(WebDriver driver) {
this.driver = driver;
}
public String getLogoText() {
return logo.getText();
}
public List<String> getMenuText() {
return menuOpt.stream().map(t -> t.getText()).collect(Collectors.toList());
}
public SOQuesWidget getFirstQues() {
return firstQues;
}
}
Question Widget - First Question
import java.util.List;
import java.util.stream.Collectors;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import io.appium.java_client.pagefactory.Widget;
public class SOQuesWidget extends Widget {
#FindBy(css="a[class='question-hyperlink']")
private WebElement quesTitle;
#FindBy(xpath=".//div[starts-with(#class,'tags')]/a")
private List<WebElement> quesTags;
protected SOQuesWidget(WebElement element) {
super(element);
}
public String getQuesTitle() {
return quesTitle.getText();
}
public List<String> getQuesTags() {
return quesTags.stream().map(t -> t.getText()).collect(Collectors.toList());
}
}
Page objects is kind of a misnomer. They don't have to be specifically full pages to follow the page object model. I would create a Table class (page object) that contains all of the locators and methods for the Table object and then include it in the pages/page objects where it appears.
For example, if the home page contains a table object, then the HomePage class would reference the Table class.

Serenity BDD with jUnit how to inject steps into setup method?

I am working on a test framework which is using Serenity, Selenium and jUnit. I have some tests which depend on user authentication. Basically I have to repeat all login steps for each test. I wanted to move these steps to a #Before method, but it seems that Steps are not being initialized in a method which is not annotated as #Test... See the code snippet below, AuthSteps instance is not being initialized.
Which are my options?
#RunWith(SerenityRunner.class)
public class MyTests extends AbstractTest {
#Managed(driver = "firefox", uniqueSession = false)
#Steps
AuthSteps auth;
#Before
public void authSetup() {
if (!authenticated){
auth.login();
//a lot of other things
}
}
#Test
public void mytest(){
//do test related stuff
}
They do. Steps will run with either #BeforeClass, #Before, #Test and so on. It seems that your if (!authenticated) statement might be excluding execution of your auth.login() step.
There's certainly not enough code provided here (like what is boolean authenticated)to clearly examine your issue, but I hope this answer helps you.

JUnit Test Suite for Selenium 2

I have converted a Selenium Test Suite into JUnit from Selenium IDE, and trying to execute from eclipse. But there is an error in my script in
suite.addTestSuite(Open_Google_IE.class);
suite.addTestSuite(Open_Google_FireFox.class);
Error message: The method addTestSuite(Class) in the type TestSuite is not applicable for the arguments (Class).
Please advise what could be the reason. I have also verified Creating Test Suite in Webdriver and updated test suite but still throws that error.
JUnit TestSuite
import junit.framework.Test;
import junit.framework.TestSuite;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
#RunWith(Suite.class)
#SuiteClasses(value = {Open_Google_IE.class, Open_Google_FireFox.class})
public class OpenGoogle {
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTestSuite(Open_Google_IE.class);
suite.addTestSuite(Open_Google_FireFox.class);
return suite;
}
public static void main(String[] args) {
junit.textui.TestRunner.run(suite());
}
}
As far as I can see, the code is OK.
addTestSuite() can only take classes that extend junit.framework.TestCase. Please make sure your classes extend that one, or find another way around...
your class has to extend SeleniumTestBase
like this one :
public class CreateAccountTestCase extends SeleniumTestBase {