I'm using the JBehave tutorial (Spring) https://github.com/jbehave/jbehave-tutorial with just 1 change, replacing PerStoryWebDriverSteps to PerStoriesWebDriverSteps.
When I try to use webDriver inside #BeforeStory I have this error message:
org.jbehave.web.selenium.DelegatingWebDriverProvider$DelegateWebDriverNotFound: WebDriver has not been found for this thread.
With this step:
public class LifecycleSteps {
private final WebDriverProvider webDriverProvider;
public LifecycleSteps(WebDriverProvider webDriverProvider) {
this.webDriverProvider = webDriverProvider;
}
#BeforeStory
public void test() {
webDriverProvider.get();
}
...
}
I just want to know if it's a bug, a misconfiguration or not possible to use webDriver in #BeforeStory?
In past I used Behat/Mink (PHP BDD) and It was not possible to use webDriver inside #BeforeStory because webDriver was not load. But in Jbehave you can select the webDriver init by using PerXXXXWebDriverSteps. And I thought it was possible to use webDriver in #BeforeStory if webDriver is init in #BeforeStories (using PerStoriesWebDriverSteps)
Related
Project Structure-image Structure I am writing some cucumber tests for my java project. When running cucumber class there are no error occurred in the console but as per the step definition script i have given the script to invoke browser so as per my assumption the step definition class or the glue is not called by the cucumber class.
Can you please check and do let me know why it is not invoked.
Code:
#RunWith(Cucumber.class)
#CucumberOptions(
features={"F:/Selinium/practise-cucumber/practise1/features/login.feature"},
glue={"F:/Selinium/practise-cucumber/practise1/src/Stepdefinition/loginmethod.java"})
public class Runcucumber {
}
Step Definition code:
public class loginmethod {
public WebDriver driver ;
#Given("^User is on Home Page$")
public void user_is_on_home_page() throws Throwable{
System.out.println("homepagre");
System.setProperty("webdriver.chrome.driver",
"F:/Selinium/practise-cucumber/practise1/driver/chromedriver1.exe");
WebDriver driver = new ChromeDriver();
driver.get("https://www.google.com/");
System.out.println("lUNCHED homepagre");
}
Browser should be invoked
Console output
Structure
Can you please change your Runcucumber class name to RuncucumberTest then try again. It happened me one time.
#RunWith(Cucumber.class)
#CucumberOptions(
features={"F:/Selinium/practise-cucumber/practise1/features/login.feature"},
glue={"F:/Selinium/practise-cucumber/practise1/src/Stepdefinition/loginmethod.java"})
public class RuncucumberTest {
}
I have been using browser invocation in #Beforeclass TestNG method using the parameter passed from testng.xml. Once the browser is invoked, I am using login test in a #BeforeMethod which is required for all the other #Tests to start. But with this setup, I am unable to run the tests in parallel. I am seeing one browser is open and login tests which is required by both tests are run in same browser and fails. All my tests are in single class file. Code structure is as below:
public class MainTest {
WebDriver driver;
BrowserFactory browser;
ReadData crmdatafile;
#BeforeClass(alwaysRun = true)
public void setup(ITestContext context) throws Exception{
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("datafile.txt").getFile());
crmdatafile = new ReadData(file.getAbsolutePath());
browser = new BrowserFactory(context.getCurrentXmlTest().getParameter("Selenium.browser"));
driver = browser.getNewBrowser();
driver.manage().deleteAllCookies();
driver.get(crmdatafile.data.get("enviornment", "url"));
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
}
#BeforeMethod()
public void login(){
System.out.println("contains the code for login which needs to be run before every test");
}
#AfterMethod
public void afterEachTest(ITestResult result) throws IOException {
driver.close();
}
#Test
public void Test1() {
System.out.println("Will run login and next steps");
}
#Test
public void Test2() {
System.out.println("Will run login and next steps");
}
public class BrowserFactory {
private WebDriver driver;
private String browser;
public BrowserFactory(String browser) {
String brow=browser.trim().toLowerCase();
if(!(brow.equals("firefox") || brow.equals("ff") || brow.equals("internetexplorer") || brow.equals("ie") || brow.equals("chrome") || brow.equals("gc"))) {
browser="ie";
}
this.browser = browser;
}
public WebDriver getNewBrowser() {
String brow = browser.trim().toLowerCase();
if(brow.equals("firefox") || brow.equals("ff")) {
System.setProperty("webdriver.gecko.driver", "drivers\\geckodriver.exe");
DesiredCapabilities capabilities = DesiredCapabilities.firefox();
capabilities.setCapability("marionette", true);
driver = new FirefoxDriver(capabilities);
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
return driver;
}else if(brow.equals("internetexplorer") || brow.equals("ie")){
driver = new InternetExplorerDriver();
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
return driver;
}else if(brow.equals("chrome") || brow.equals("gc")){
System.setProperty("webdriver.chrome.driver", "drivers\\chromedriver.exe");
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
ChromeOptions options = new ChromeOptions();
options.addArguments("test-type");
capabilities.setCapability("webdriver.chrome.binary","drivers\\chromedriver.exe");
capabilities.setCapability(ChromeOptions.CAPABILITY, options);
driver = new ChromeDriver(capabilities);
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
return driver;
}
return null;
}
How can I improve the above structure to run tests in parallel and using a different browser for each test?
Your test code has some issues.
You are instantiating a webdriver instance in your #BeforeClass annotated method and that is being shared by all your #Test annotated test methods. You are also invoking driver.close() in an #AfterMethod annotated method.This is a recipe for disaster because AFAIK driver.close() is equivalent to driver.quit() if you are having only one web browser instance. So what this means is that your second test method will not have a valid browser (if you are running sequentially).
If you are running in parallel, then all your test methods are going to be competing for the same browser, which is now going to cause race conditions and test failures.
You should ideally speaking move the logic of your setup() method into a listener which implements IInvokedMethodListener interface and then have this listener inject the webdriver instances into a ThreadLocal variable, which your #Test methods can then query.
You can refer to my blog post which talks in detail on how to do this.
Please check if that helps.
Here is the thing, as far as I can see you're not using annotations right and (probaly) testNG as well.
If you want to create browser instance before each test you may want to use #BeforeTest annotation. Also you may perform your test set up in this method as well. #BeforeClass annotation will be executed only once before this particular class will be executed.
It's a good idea to split tests that do different things into separate test files, case your tests do almost the same, but say params for tests are different - it's a good idea to use #DataProvider. Otherwise maybe you may want to extend your basic test with setup.
If you just want to re-execute same tests, but with different browser - consider relaunching your test job with different params or using #DataProvider as described above.
As far as I remember there are several ways to run testNG in parallel: Methods, Classes, Tests, Instances - figure out which one you need and which one works better with your setup.
I'm trying to use the same code with Appium driver and Java , TestNG but with ChromeDriver I changed the configuration by adding that code :
File file = new File("C:/QA/Emna/chromedriver.exe");
System.setProperty("webdriver.chrome.driver", file.getAbsolutePath());
WebDriver driver = new ChromeDriver();
The problem is that any test case the chrome window is opened a new one, even if my tests are in a correct order with Priority (by TestNG).
Is there a way to work in only one window?
WebDriver driver = new ChromeDriver(); is what opens a new browser each time. Move it to #BeforeClass section and use the same instance in all the tests.
You need to move you code snippet in any #Before type of TestNG methods. Lets say your all test cases are in a TestNG class then
Here is how it should look like:
#BeforeClass
public void deSetup(){
File file = new File("C:/QA/Emna/chromedriver.exe");
System.setProperty("webdriver.chrome.driver", file.getAbsolutePath());
WebDriver driver = new ChromeDriver();
}
But if this is not the case, what I mean by this, that your test cases are spread across the multiple TestNG classes then the best way is to have a Singleton class to load and initialize the ChromeDriver. Call method of the Singleton class to instantiate the ChromeDriver in any one of method annotated as #BeforeSuite #BeforeTest or #BeforeGroups. And have a reference variable of WebDriver type in evelry test class and assigne the previously initialized ChromeDriver to this reference variable in #BeforeClass method.
In such a way, ChromeDriver will be instantiated only once when any one of #BeforeSuite #BeforeTest or #BeforeGroups method runs and will be available in every TestNG class once #BeforeClass runs.
This way you can work in only one Chrome window.
I have fixed my problem by this way in #BeforeClass:
#BeforeClass
public static void before() {
// check active session
System.out.println("Becore Test Method");
File file = new File("C:/QA/Emna/chromedriver.exe");
System.setProperty("webdriver.chrome.driver", file.getAbsolutePath());
wd = new ChromeDriver();
}
I made an instance like that:
static WebDriver driver ;
Then in every test I put the following :
#Test
public static void run1() {
//my tests using wd
}
#Test
public static void run2() {
//my tests using wd
}
I am new to cucumber testing as well as selenium testing.Please help me to run all cucumber test cases in single browser.As for now i am creating new WebDriver object in each cucumber step_def for feature file.
The solution is, Using / passing the same Web Driver object across your step_def. From your Question i assume, you have multiple Step Def files, If the stories are small and related put all of them in a single step_def file and have a single Web driver object. If it is not the case, invoke every step_def with a predefined Driver object that is globally declared in the configuration loader.
For using one browser to run all test cases use singleton design pattern i.e make class with private constructor and define class instance variable with a private access specifier.Create a method in that class and check that class is null or not and if it is null than create a new instance of class and return that instance to calling method.for example i am posting my code.
class OpenBrowserHelp {
private WebDriver driver;
private static OpenBrowserHelp browserHelp;
private OpenBrowserHelp() {
this.driver = new FirefoxDriver()
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.manage().window().maximize();
}
public static OpenBrowserHelp getOpenBrowserHelp() {
if (null == browserHelp) {
browserHelp = new OpenBrowserHelp();
}
return browserHelp;
}
WebDriver getDriver() {
return driver
}
void setDriver(WebDriver driver) {
this.driver = driver
}
public void printSingleton() {
System.out.println("Inside print Singleton");
}
Now, where ever you need to create browser instance than use
WebDriver driver = OpenBrowserHelp.getOpenBrowserHelp().getDriver();
I am having issues trying to get my Fluentlenium code to run inside the WebDriver Firefox Driver. I need Fluentlenium to execute inside the WebDriver Firefox Driver instead of opening it's own browser. I think I need to override this but I am not exactly sure how to do this. Any help would greatly appreciated. Thanks! Here is what I have for code:
WebDriver driver = new FirefoxDriver();
#Test
public void create_a_picklist()
{
// Go to Page
goTo("http://www.google.com");
}
What happens is that it opens two browsers. One is from the Firefox Driver and the other must be the default browser from the goTo from Fluentlenium. I need it to run this code inside the Firefox Driver window and not open it's own window from Fluentlenium.
By default, it launchs a Firefox browser so that's sufficient :
public class Test extends FluentTest {
#Test
public void go_to_google()
{
goTo("http://www.google.com");
}
}
And nothing more :)
Ok. Looks like I figured it out. Here is what I did to override the browser:
public class Test extends FluentTest {
// Defines the Driver
public WebDriver driver = new FirefoxDriver();
// Overrides the default driver
#Override
public WebDriver getDefaultDriver() {
return driver;
}
#Test
public void go_to_google()
{
goTo("http://www.google.com");
}
}