Getting Exception In Initializer error from maven- Selenium test - java

i am getting an Exception In Initializer error in my code and don't know what i am doing wrong, please help !i am happy to answer if you have any questions. Below is the error i am getting from maven:
[ERROR] Failures:
[ERROR] Homepage_Test.startURL:13->BaseClass.globalDriver:26 ยป ExceptionInInitializer.
//My Homepage_Test which includes all tests. startURL() invokes webdriver and runs to get website:
public class Homepage_Test extends BaseClass{
#BeforeTest
public void startURL() {
globalDriver();
}
#Test
public void search_product() {
Homepage_Methods.search_and_add();
}
#Test
public void verify_product_text() {
Homepage_Methods.verify_search();
}
#Test
public void scroll_down_page() {
Homepage_Methods.scroll_down_verify_text();
}
#AfterClass
public void clear_field() {
Homepage_Methods.clear_inputfield();
}
}
// My BaseClass:
public class BaseClass {
public static void globalDriver() {
System.setProperty("webdriver.gecko.driver" , System.getProperty("user.dir")+"/resources/geckodriver.exe");
WebDriver driver = new FirefoxDriver();
#SuppressWarnings("unused")
Shop_Page_Objects cpo = new Shop_Page_Objects(driver);
#SuppressWarnings("unused")
Homepage_Objects hpom = new Homepage_Objects(driver);
#SuppressWarnings("unused")
Shop_Page_Methods spm = new Shop_Page_Methods(driver);
#SuppressWarnings("unused")
Homepage_Methods hpm = new Homepage_Methods(driver);
DesiredCapabilities dc = new DesiredCapabilities();
FirefoxOptions options = new FirefoxOptions();
options.setHeadless(true);
dc.setCapability(FirefoxOptions.FIREFOX_OPTIONS,options);
driver.manage().timeouts().implicitlyWait(6000, TimeUnit.SECONDS);
driver.get("blabla website");
}
}
//Line 26 of BaseClass contains Shop_Page_Methods which is very long but here is the snippet:
public class Shop_Page_Methods extends BaseClass{
private static WebDriver driver;
public Shop_Page_Methods(WebDriver driver) {
Shop_Page_Methods.driver = driver ;
}
public static WebElement product_1_to_add_to_cart = Shop_Page_Objects.get_cart_product_1();
public static List<WebElement> all_products = Shop_Page_Objects.get_All_Products();
public static int products_count = Shop_Page_Objects.get_All_Products().size();
public static List<WebElement> all_price = Shop_Page_Objects.get_price();
public static String remove_number = Shop_Page_Objects.get_number_to_remove().getText();
public static String[] remover_1 = remove_number.split("");
public static int remove_number_1 = Integer.parseInt(remover_1[0]);

i figured out the issue was that i was doing the following before actually clicking/switching to their container:
public static String remove_number = Shop_Page_Objects.get_number_to_remove().getText();
public static String[] remover_1 = remove_number.split("");
public static int remove_number_1 = Integer.parseInt(remover_1[0]);

Related

How to replace static driver method

public class CommonFunctions {
public static WebDriver driver;
public void openWebsite(String url) {
driver.get(url);
}
public void closeBrowser() {
driver.close();
}
}
public class TestCase {
CommonFunctions commonFunctions = new CommonFunctions();
#BeforeMethod
public void openWeb() {
homePage.openWeb();
}
#Test
public void navigateLoginPage() {
homePage.login();
}
#AfterMethod
public void closeBrowser() {
commonFunctions.closeBrowser();
}
}
I have two class (commonfunction,homepage and testcase). When I run code without "static" at "public static Webdriver driver", the code throw nullpointerexception at function "closeBrowser". How to fix this error. I don't want use method "public static Webdriver driver" as code.
You need to initialize your driver variable in your CommonFunctions class.
WebDriver driver = new WebDriver(... etc);
Or, write a constructor that initializes this variable.
public class CommonFunctions
{
public WebDriver driver;
public CommonFunctions() // Constructor
{
driver = new WebDriver();
}

Figuring Out How To Take Screenshots with TestNG on Test Failure

Okay, I've looked on this topic for quite a bit and have tried multiple solutions to my problem, but I seem to keep getting into roadblocks. I'm trying to setup a general TakeScreenshot after it hits the max of retry attempts with my RetryAnalyzer class. However, I keep getting hit with ClasscastExceptions when adding the Driver and I'm having trouble how to get that same driver initialized in the Base Test, (besides setting to static). Here are my classes I have setup for Screenshot Capture:
Driver Class:
public class Driver implements WebDriver {
protected WebDriver driver;
String browserName;
public static JavascriptExecutor js;
public Driver (String browserName) {
this.browserName = browserName;
if(browserName.equalsIgnoreCase("chrome")) {
System.setProperty("webdriver.chrome.driver", "./resources/webdrivers/chromedriver_win32/chromedriver.exe");
this.driver = new ChromeDriver();
js = (JavascriptExecutor) this.driver;
}
// Other methods for different browsers
BaseTest (Start Portion):
#Listeners({TestMethodListener.class, ScreenshotListstener.class})
public class BaseTest {
protected Driver driver;
DummyTestAccount dummyAccount = new DummyTestAccount();
String browserName = getParamater("browser");
#BeforeClass(alwaysRun = true)
public void setUp() {
driver = new Driver(browserName);
driver.manage().window().maximize();
}
private String getParamater(String name) {
String value = System.getProperty(name);
if(value == null) {
throw new RuntimeException(name + "missing parameter");
}
return value;
}
//Further setup for my extended test classes
RetryAnalyzer:
public class RetryAnalyzer extends BaseTest implements IRetryAnalyzer {
int count = 0;
private static int maxTry = 1;
ScreenshotListstener picCapture = new ScreenshotListstener();
public boolean retry(ITestResult arg0) {
if(count < maxTry) {
count++;
return true; //Retry for flaky tests with unexpected variables
} else {
picCapture.onTestFailure(driver, arg0);
return false; //Don't retry the failed test Capture Screenshot.
}
}
Screenshot Class:
public class ScreenshotListstener extends TestListenerAdapter {
public void onTestFailure(Driver driver, ITestResult result) {
Calendar calendar = Calendar.getInstance();
String methodName = result.getMethod().getMethodName();
SimpleDateFormat formater = new SimpleDateFormat("dd_MM_yyyy_hh_mm_ss");
File bugPic = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
try {
Files.copy(bugPic, new File("./target/surefire-reports/error-pics/"+ methodName + "_" +formater.format(calendar.getTime()) + ".png"));
} catch(IOException e) {
e.printStackTrace();
}
}
}
Currently with this setup, I'm getting hit with a NullPointerException occurring in ScreenshotListener class when initializing on the bugPic File instance. Is there something that I'm missing? Would this current setup be following towards a good practice for test frameworks?
Any advice is helpful.
Thanks.
(Update):
Figured out my issue thanks to Grasshopper's advice.
Driver Class:
public class Driver implements WebDriver {
protected WebDriver driver;
String browserName;
public static JavascriptExecutor js;
public TakesScreenshot bugCapture;
public Driver (String browserName) {
this.browserName = browserName;
if(browserName.equalsIgnoreCase("chrome")) {
System.setProperty("webdriver.chrome.driver", "./resources/webdrivers/chromedriver_win32/chromedriver.exe");
this.driver = new ChromeDriver();
js = (JavascriptExecutor) this.driver;
bugCapture = (TakesScreenshot)driver;
}
// Other methods for different browsers
BaseTest (Start Portion):
#Listeners({TestMethodListener.class, ScreenshotListstener.class})
public class BaseTest {
protected Driver driver;
public static final ThreadLocal<Driver> driverThread = new ThreadLocal<Driver>();
DummyTestAccount dummyAccount = new DummyTestAccount();
String browserName = getParamater("browser");
#BeforeClass(alwaysRun = true)
public void setUp() {
driver = new Driver(browserName);
driver.manage().window().maximize();
driverThread.set(driver);
}
private String getParamater(String name) {
String value = System.getProperty(name);
if(value == null) {
throw new RuntimeException(name + "missing parameter");
}
return value;
}
//Further setup for my extended test classes
RetryAnalyzer:
public class RetryAnalyzer extends BaseTest implements IRetryAnalyzer {
int count = 0;
private static int maxTry = 1;
ScreenshotListstener picCapture = new ScreenshotListstener();
public boolean retry(ITestResult arg0) {
if(count < maxTry) {
count++;
return true; //Retry for flaky tests with unexpected variables
} else {
picCapture.onTestFailure(driverThread.get(), arg0);
return false; //Don't retry the failed test Capture Screenshot.
}
}
Screenshot Class:
public class ScreenshotListstener extends TestListenerAdapter {
public void onTestFailure(Driver driver, ITestResult result) {
Calendar calendar = Calendar.getInstance();
String methodName = result.getMethod().getMethodName();
SimpleDateFormat formater = new SimpleDateFormat("dd_MM_yyyy_hh_mm_ss");
File bugPic = driver.bugCapture.getScreenshotAs(OutputType.FILE);
try {
Files.copy(bugPic, new File("./target/surefire-reports/error-pics/"+ methodName + "_" +formater.format(calendar.getTime()) + ".png"));
} catch(IOException e) {
e.printStackTrace();
}
}
}

JUnit passing parameters between class

I have a scenario as follows that I'm not sure from where to start,
File name should be passed as an argument param when running the jar file
say for example I want to test a set of data from external file and I have a super class (Test Suite) that have number one and number two
and there are two test classes that should extend this class and perform the tests.
I'm currently new to JUnit so I'm lacking many concepts and need someone's help.
I have class CoreManager which executes the main
public static void main(String[] args)
{
if (Arrays.asList(args).contains("Import"))
{
accountInfo = new ArrayList<>();
int ImportIndex = Arrays.asList(args).indexOf("Import");
String fileName = args[ImportIndex+1];
if (fileName.contains("xml"))
{
ParseXML parseXML = new ParseXML();
accountInfo = parseXML.ParseAccounts(fileName);
Result result = JUnitCore.runClasses(LoginTestSuite.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
System.out.println(result.wasSuccessful());
}
}
}
And Suite Class
#RunWith(MockitoJUnitRunner.class)
#Suite.SuiteClasses({
Login.class,
SignUp.class
})
public class LoginTestSuite {
public static WebDriver driver;
public static ArrayList<AccountInfo> Account;
public static int SecondsToWait;
public LoginTestSuite(WebDriver driver,ArrayList<AccountInfo> Account,int
secondsToWait)
{
this.Account = Account;
this.SecondsToWait = secondsToWait;
this.driver = driver;
}
}
And Test Class
public class Login {
private static WebDriver driver;
private static ArrayList<AccountInfo> Account;
private static int SecondsToWait;
private static final Logger logger = Logger.getLogger(Login.class.getName());
#BeforeClass
public void init(){
this.driver = LoginTestSuite.driver;
this.Account = LoginTestSuite.Account;
this.SecondsToWait = LoginTestSuite.SecondsToWait;
}
#Before
public void Setup(){
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(SecondsToWait,
TimeUnit.SECONDS);
driver.manage().timeouts().pageLoadTimeout(SecondsToWait,
TimeUnit.SECONDS);
}
#After
public void TearDown(){
driver.quit();
}
#Test
public void TestUserLogin() throws Exception
{
// Logic
}
Your code looks muddled and contains several poor quality constructs. Most importantly, I don't see a distinction between test code and production code. Which is which?
This could be production code:
public class App {
public static void main(String[] args) {
AccountReader accountReader = new AccountReader();
List<AccountInfo> accounts = accountReader.read(args);
// maybe do something with those accounts?
}
}
public class AccountReader {
private ParseXML parseXML;
public AccountReader() {
this.parseXML = new ParseXML();
}
// extra constructor to allow dependency injection from test
protected AccountReader(ParseXML parseXML) {
this.parseXML = parseXML;
}
public List<AccountInfo> read(String[] args) {
return parseXML.ParseAccounts(getFileName(args));
}
private String getFileName(String[] args) {
List<String> arguments = Arrays.asList(args);
int importIndex = arguments.indexOf("Import");
if (importIndex < 0) {
throw new RuntimeException("Missing Import argument");
}
int fileNameIndex = importIndex + 1;
if (fileNameIndex >= arguments.size()) {
throw new RuntimeException("Missing fileName argument");
}
String fileName = args[fileNameIndex];
if (!fileName.endsWith(".xml")) {
throw new RuntimeException("Can only import XML files");
}
return fileName;
}
}
And this could be a test for it:
public AccountReaderTest {
private AccountReader instance;
#Mock // creates a mock instance which we can give desired behavior
private ParseXML parseXML;
#Mock
List<AccountInfo> accounts;
#Before
public void setUp() {
instance = new AccountReader(parseXML);
}
#Test
public void testHappy() {
// SETUP
String fileName = "test.xml";
// specify desired behavior of mock ParseXML instance
when(parseXML.ParseAccounts(fileName).thenReturn(accounts);
// CALL
List<AccountInfo> result = instance.read(new String[] { "Import", fileName });
// VERIFY
assertEquals(accounts, result);
}
#Test(expected = RuntimeException.class)
public void testMissingImport() {
instance.read(new String[] { "notImport" });
}
#Test(expected = RuntimeException.class)
public void testMissingFileName() {
instance.read(new String[] { "Import" });
}
#Test(expected = RuntimeException.class)
public void testNotXml() {
instance.read(new String[] { "Import", "test.properties"});
}
}

Cannot store WebDriver as global variable and execute a test more than once in the same Swing instance

In Swing, I have a JButton which executes the following test script when clicked on:
#RunWith(Parameterized.class)
public class ExampleTest{
private static csvTools csvTools = new csvTools();
private static WebDriver driver = CreateWebDriver.getDriver("chrome");
public static URLS urls;
// ..
// Data variables
private String fullName;
// ..
public ExampleTest(Map<String, String> testDataRow) {
this.fullName = testDataRow.get("Full name");
//..
}
#Rule
public TestName currentlyRunningTest = new TestName();
#Rule
public final ErrorCollector collector = new ErrorCollector();
#Parameterized.Parameters
public static Collection<Map<String, String>> testData() throws Exception {
return csvTools.getTests("ExampleTestData.csv");
}
#BeforeClass
public static void openBrowser() throws Exception {
page = new BasePage(driver);
userInformation = new UserInformation();
loginPage = new LoginPage(driver);
registrationPage = new RegistrationPage(driver);
evidenceCollector = new resources.EvidenceCollector(ExampleTest.class.getName());
}
#Before
public void setUp() throws Exception {
csvTools.saveData(currentlyRunningTest, "Fail/Pass", "");
evidenceCollector.newTestCase();
}
#Test
public void ExampleTest() throws Exception {
try {
driver.get(URLS.LOGINPAGEURL);
driver.findElement(By.id("d"));
//..
driver.get("examplesite");
page.screenShot(driver);
}
#After
public void tearDown() throws Exception {
evidenceCollector.moveScreenshotsAndTestData("ExampleTestData.csv");
}
#AfterClass
public static void closeBrowser() {
driver.quit();
}
}
The issue I have is, it will not let me execute the same script more than twice in the same Swing GUI instance. I have identified that this line, is the culprit:
private static WebDriver driver = CreateWebDriver.getDriver("chrome");
I determied this by commenting the line out and moving:
WebDriver driver = CreateWebDriver.getDriver("chrome");
into the test itself, where it is then possible to execute the test more than once in the same Swing GUI instance. However, as the the chrome driver is no longer stored as a global variable I cannot access it outside of the test, such as as #BeforeClass and #After
Here is the GUI Code:
JButton exTest1 = new JButton("Run ExampleTest");
exTest1.setLocation(290, 70);
exTest1.setSize(120, 30);
buttonPanel.add(exTest1);
exTest1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (exTest1.isEnabled()) {
executor.execute(new Runnable() { // This is how we run stuff in background. You can use lambdas instead of Runnables.
public void run() {
JUnitCore junit = new JUnitCore();
final Result result = junit.run(ExampleTest.class);
SwingUtilities.invokeLater(new Runnable() { // Now we go back to the GUI thread
public void run() {
errorMessageDisplay(result);
}
});
}
});
}
}});
What about initializing the driver in #BeforeClass ?
#RunWith(Parameterized.class)
public class ExampleTest{
private static csvTools csvTools = new csvTools();
private static WebDriver driver;
// ...
#BeforeClass
public static void openBrowser() throws Exception {
driver = CreateWebDriver.getDriver("chrome");
page = new BasePage(driver);
// ...
}
// ...
}

How make webdriver not to close browser window after each test?

I'm new in both Selenium WebDriver and Java. I have some webservices on my site on page /someservice.php. I've wrote few tests on Selenuim and they work fine. Code example (Main Class):
public class SiteClass {
static WebDriver driver;
private static boolean findElements(String xpath,int timeOut ) {
public static void open(String url){
//Here we initialize the firefox webdriver
driver=new FirefoxDriver();
driver.get(url);
}
public static void close(){
driver.close();
}
WebDriverWait wait = new WebDriverWait( driver, timeOut );
try {
if( wait.until( ExpectedConditions.visibilityOfElementLocated( By.xpath( xpath ) ) ) != null ) {
return true;
} else {
return false;
}
} catch( TimeoutException e ) {
return false;
}}
public static Boolean CheckDiameter(String search,String result){
driver.findElement(By.xpath("//input[#id='search_diam']")).sendKeys(search);
WebDriverWait wait = new WebDriverWait(driver, 5);
WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//div[#class='ac_results'][last()]/ul/li")));
WebElement searchVariant=driver.findElement(By.xpath("//div[#class='ac_results'][last()]/ul/li"));
Actions action = new Actions(driver);
action.moveToElement(searchVariant).perform();
driver.findElement(By.xpath("//li[#class='ac_over']")).click();
Boolean iselementpresent = findElements(result,5);
return iselementpresent;
}
}
Code Example (Test Class)
#RunWith(Parameterized.class)
public class DiamTest {#Parameters
public static Collection<Object[]> diams() {
return Arrays.asList(new Object[][] {
{ "111", "//div[#class='jGrowl-message']",true},
{ "222", "//div[#class='jGrowl-message']",false},
{ "333", "//div[#class='jGrowl-message']",true},
});
}
private String inputMark;
private String expectedResult;
private Boolean assertResult;
public DiamTest(String mark, String result, boolean aResult) {
inputMark=mark;
expectedResult=result;
assertResult=aResult;
}
#BeforeClass
public static void setUpClass() {
}
#AfterClass
public static void tearDownClass() {
}
/**
* Test of CheckDiameter method, of class CableRu.
*/
#Test
public void testCheckDiameter() {
SiteClass obj=new SiteClass();
obj.open("http://example.com/services.php");
assertEquals(assertResult, obj.CheckDiameter(inputMark, expectedResult));
obj.close();
}
}
Now I have 2 tests like that with 3 parameters each (total 6 variants). As you can see in every variant I create new browser window and when I run all 6 variants that take too much time (up to 80 seconds).
How can I run all variants in one browser window to speed up my tests?
Just move contents of public static void close() method from your SiteClass to tearDownClass() method in DiamTest class. In this way the browser window will be closed when the class execution finished (because of #AfterClass annotation). Your code then should look like this:
//DiamTest class
#AfterClass
public static void tearDownClass() {
driver.close();
}
It's also a good practice to move browser window initialization to setUpClass() method which will be executed before each test class (according to #BeforeClass annotation)
//DiamTest class
#BeforeClass
public static void setUpClass() {
//Here we initialize the firefox webdriver
driver=new FirefoxDriver();
driver.get(url);
}
What you need to do is share your help class with all your tests, this mean, you should create an instance of SiteClass inside your setUpClass method.
This method are annotated with #BeforeClass assuring your test class will create this method will be executed before all the test be executed.
You can read more about #BeforeClass in jUnit doc: or have a simple overview in this response.
You will also need do some rewrite some code to allow share the driver with the another test, something like this:
#RunWith(Parameterized.class)
public class DiamTest {
#Parameters
public static Collection<Object[]> diams() {
return Arrays.asList(new Object[][] {
{ "111", "//div[#class='jGrowl-message']",true},
{ "222", "//div[#class='jGrowl-message']",false},
{ "333", "//div[#class='jGrowl-message']",true},
});
}
private String inputMark;
private String expectedResult;
private Boolean assertResult;
private static SiteUtil siteUtil;
public DiamTest(String mark, String result, boolean aResult) {
inputMark=mark;
expectedResult=result;
assertResult=aResult;
}
#BeforeClass
public static void setUpClass() {
siteUtil = new SiteUtil();
}
#AfterClass
public static void tearDownClass() {
siteUtil.close();
}
#Test
public void testCheckDiameter() {
siteUtil.open("http://example.com/services.php");
assertEquals(assertResult, obj.CheckDiameter(inputMark, expectedResult));
}
}
and:
public class SiteClass {
static WebDriver driver;
public SiteClass() {
driver = new FirefoxDriver();
}
public void open(String url){
driver.get(url);
}
...
Tip:
You should read about the TestPyramid.
Since functional tests are expensive, you should care about what is really necessary test. This article is about this.

Categories

Resources