I was trying to run TestNG script via Selenium WD 3.6 Version
The script just need to browse to Facebook via Chrome Browser
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
public class FB {
ChromeDriver driver= new ChromeDriver ();
#BeforeTest
public void beforeTest() {
System.setProperty("webdriver.chrome.driver","C:\\chromedriver.exe");
driver.manage().window().maximize();
}
#Test
public void URL()
{
driver.get("https://www.facebook.com/");
}
}
I received the following error in console:
[RemoteTestNG] detected TestNG version 6.12.0
org.testng.TestNGException:
Cannot instantiate class Staging.FB
Please advise what i did wrong
Thanks
I'd recommend changing your driver member type to WebDriver, then, instead of initializing at the class level, do so inside your #BeforeTest method.
If we look at the TestNG lifecycle, the FB class gets instantiated before the #BeforeTest method runs. In order for that to happen, the WebDriver instance field needs to resolve. Since you appear to be using a system property to set the location of the Chrome Driver executable, this initialization cannot take place without throwing an error (since this happens in #BeforeTest). By moving the WebDriver initialization after the property declaration, initialization can run successfully.
So...
public class FB {
WebDriver driver;
#BeforeTest
public void beforeTest() {
System.setProperty("webdriver.chrome.driver","C:\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().window().maximize();
}
// Then add your #Test method(s) here...
}
Related
I am fairly new to software testing (3 -4 years) and I work as a sole tester in an organisation. Unfortunately I have not have a mentor to help me when building the automated test suite.
The main issue I want to overcome is tests failing because a previous test failed. This is mainly because the tests in the WebDriver Selenium suite are used to setup further tests. Is there some way I can make my tests not so dependent on previous 'setup' tests? Let me describe a typical scenario:
To create a transaction, the following things are prerequisites and must be set up in the system first. These are all done as individual tests on the site first:
Source Country
Source Currency
Destination Country
Destination Currency
Commission charge
Agent profile
Sender profile
Receiver profile
Only then can I run the tests to actually create a transaction.In some cases, there are more steps involved in setting up the system before a tests can be run. The problem arises when, for example, the Destination Currency test fails. This will cause all subsequent tests to fail.
What can I do to make the tests more independent so if a previous 'setup' test fails for any valid reason, it doesn't affect the remainder of the tests? I just want to follow best test practices and cannot find the answer to this question anywhere online.
Many thanks in advance.
If your tests can pass independently then it can be done using cucumber-guice injection to independently open browser for each scenario.
You may have to arrange your tests as scenarios like below
Scenario: set source country
Given source country is setup
Scenario: set source currency
Given source currency is setup
OR you can use example feature of cucumber. In this method you may to do extra parsing in step defs depending on how much different it is to set up each source
Scenario Outline: login registration
Given these <source> are set up with <details>
Examples:
|source|details|
|"country" |"xyz"|
|"currency" |"abc"|
...
...
cucumber-guice will open one browser for each scenario in both above methods ( cucumber consider each example line a scenario)
Now the actual guice implementation. To use guice you will need cucumber-guice dependency
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-guice</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>4.2.3</version>
<scope>test</scope>
</dependency>
These are the classes that I use to independently open browser for each scenario. In a chromemanager class you do
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeDriverService;
public class ChromeManager extends DriverManager {
protected ChromeDriver driver;
#Override
protected WebDriver createDriver() {
System.setProperty("webdriver.chrome.driver", "/Users/../chromedriver");
return driver = new ChromeDriver(ChromeDriverService.createDefaultService());
}
#Override
public WebDriver getDriver() {
if (driver == null) {
this.createDriver();
}
return driver;
}
}
Driverfactory class
import org.openqa.selenium.WebDriver;
public class DriverFactory {
public WebDriver getManager() {
return new ChromeManager().getDriver();
}
}
Drivermanager class
import org.openqa.selenium.WebDriver;
public abstract class DriverManager {
protected abstract WebDriver createDriver();
public abstract WebDriver getDriver();
}
and then in a global class
import org.openqa.selenium.WebDriver;
import io.cucumber.guice.ScenarioScoped;
#ScenarioScoped
public class Global {
public WebDriver driver;
public WebDriverWait wait;
public Global() {
driver = new DriverFactory().getManager();
wait = new WebDriverWait(driver, 3000);
//any class you instantiate here will be injected in below initialIT class for each scenario
}
}
and finally your test class
import com.google.inject.Inject;
import com.test.support.Global;
public class InitialIT {
public static ChromeDriver driver ;
#Inject
Global global;
#Test
#Given("source country is setup")
public void setCountry() throws MalformedURLException {
global.driver.get(yourSite);
}
#Test
#Given("source currency is setup")
public void setCurrency() throws MalformedURLException {
global.driver.get(yourSite);
}
#After
public void closeBrowser() {
global.driver.quit();
}
}
How to initialize the driver so it can be used by all classes
Hi All,
I am writing a test automation framework in JAVA using Appium, Selenium and Cucumber.
I start off by declaring an Appium Driver in one of my test step files and then this gets cast to an Android Driver or iOS Driver depending on the app under test.
I need some help please - I need all of my class files to have access to this instance of the driver but I’m not sure how to do this. The test is driven from the feature file and some of the test steps are in different class files so how can they all access this instance of the driver?
Thanks
Matt
You can make an initialising method in the class where all the other config setup can be done and then you can make an instance of that class to call the getDriver method.
For example:
public class initialiseDriver{
private static AppiumDriver<MobileElement> driver;
public AppiumDriver<MobileElement> getDriver() throws IOException {
if (PLATFORM_NAME.equals("Android")) {
// setup the android driver
} else if (PLATFORM_NAME.equals("iOS")) {
// setup the ios driver
}
return driver;
}
}
You can just call this method where you want to use the driver. Ideally, you should initialise the driver by calling this method in the #BeforeSuite/#BeforeClass method, so that you don't need to call this method everytime you start your script as it would be called implicitly with the #BeforeSuite/#BeforeClass.
you can define your AppiumDriver as static
public class AppiumHelper(){
public static AppiumDriver<MobileElement> driver;
public void setupDriver(){
//define your DesiredCapabilities
//initialize your driver
}
Then you can use your driver in your test method like
public void test1(){
MobileElement element= AppiumHelper.driver.findElementById("elements id");
}
The serenity PageObject class provides an inbuilt getDriver() method which you can call wherever you want to initialize the driver(preferably in the test classes). Avoid trying to initialize the driver in any of your step definations/step libraries(Managing using #Managed annotation) else it will throw a :
null pointer exception.
The code is working fine but why? without creating object of class Testing123 How we are able to access that driver?
public class Testing123 {
WebDriver driver ;
#Test
public void test1() {
driver = new ChromeDriver();
driver.get("http://google.com");
}
}
TestNG framework is taking care of creating an instance of your test class behind the scenes. Basically by annotating your method with '#Test' the annotation processor associate the class to the test runner. For further info look at: http://makeseleniumeasy.com/2018/06/08/testng-tutorials-21-why-dont-we-require-a-main-method-in-testng-class-for-execution-of-methods/
Getting an error below after running test2.java running as TestNG if I run it as Java Application everything is working. What does the error mean and can anyone help me with this using TestNG and Java. I am using Webdriver and Eclipse and just want to do this simple trick to apply for my test scripts.
SKIPPED: main org.testng.TestNGException: Method main requires 1
parameters but 0 were supplied in the #Test annotation.
Here is my code for Test1.java
package firsttestngpackage;
import org.testng.annotations.Test;
#Test
public class Test1{
public void message(){
System.out.println("Test");
}
}
Here is my code for Test2.java
package firsttestngpackage;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
#Test
public class Test2{
public static void main(String[] args){
Test1 class1 = new Test1();
class1.message();
}
}
If you use #Test in the class level, all the public methods are considered test methods. You need to supply parameters to the main method as it expects an argument.
Just change it to public void main()
It looks you are using TestNG in wrong way. You don't need java main method. Just use annotation #Test and then run class with TestNG (org.testng.TestNG) and defined .xml test suite as Java Application or in Eclipse runner. TestNG invokes all tests methods so you don't have to call it manually.
i got it to work by removing "String[] args"
package firsttestngpackage;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
#Test
public class Test2{
public void main(){
Test1 class1 = new Test1();
class1.message();
}
}
jaroslav is right.you are using #Test annotation in a wrong way.While using testNG framework u r not using the main method to run the test.u running it as TestNG tests
Firstly the above comments are right. Don't use main method if you are using testNG annotations. Main method can only be used in #Beforeclass and #Afterclass. Also no need of (String[] args).
If you are still facing problem with TestNg,
Make sure you have installed it correctly.
Use this code before your 1st test case (#Test)
#BeforeTest
public void setup ()
{
System.setProperty("webdriver.chrome.driver", "*location of your driver*");
ChromeOptions options = new ChromeOptions();
options.addArguments("test-type");
options.addArguments("start-maximized");
options.addArguments("--js-flags=--expose-gc");
options.addArguments("--enable-precise-memory-info");
options.addArguments("--disable-popup-blocking");
options.addArguments("--disable-default-apps");
options.addArguments("test-type=browser");
options.addArguments("disable-infobars");
driver = new ChromeDriver(options);
driver.manage().deleteAllCookies();
}
Let me know if this helps.
Here is how I declare firefox driver:
public static WebDriver driver = new FirefoxDriver();
I place the code above outside main and within my class (global)
Here is how I declare chrome driver:
System.setProperty("webdriver.chrome.driver", "/path/xxx/xxx/xx");
WebDriver driver = new ChromeDriver();
I place the code above in main
Here is the issue:
I want to make the ChromeDriver as a global but I NEED to set the property before doing so. But I place the System.setProperty("xx","xx"); within the main body. Cuz it gives error when placed outside.
Here is a user trying to do the same thing as me. Trying to run different browsers using the same driver : How to run Selenium tests in multiple browsers for cross-browser testing using Java?
The answer is involves declaring the driver in the main body and not as a constant before.
My issue: All functions need driver declaration from before. Calling functions which use driver. If I declare driver in main, I need to continuously pass it as a parameter to all the functions. I do not wish to do that. Here is an example function
public static void a(){
driver.findElement(By.id("hi"));
}
How about something like:
class SomeTest {
static WebDriver driver;
public static void main(String[] args) {
System.setProperty("key", "value");
driver = new ChromeDriver();
}
public static void a() {
driver.findElement(By.id("hi"));
}
}