How do run each browserdriver based on enum list value? - java

I am using the code found in the first answer on this page: Click Here
I an able to run this successfully and choose the browser by changing environment USED_DRIVER line for a number of different browsers.
I was wandering if it is possible to run a test runs it through each case once before finishing, i.e. so that it has been tested on each of the selected browsers once I have had a go at using for, and if but havnt been very successful.
Example Test
driver.get("calc.php");
driver.findElement(By.name("firstnumber")).sendKeys("2");
Thread.sleep(500);
driver.findElement(By.name("secondnumber")).sendKeys("2");
Thread.sleep(500);
driver.findElement(By.name("Calculate")).click();
Thread.sleep(500);
driver.findElement(By.name("save")).click();
Thread.sleep(500);

I believe what you are asking for is to run a single test multiple times, once for each browser.
There are different ways you can do this...I'll start with the simplest (but hardest to maintain in the future, so make sure you understand each choice before choosing):
Solution 1: The simplest way would be to put a for loop around your test. You will have a List of different WebDrivers that the tests will run on. It would look something like this:
WebDriver[] drivers = new WebDriver[]{firefoxDriver, chromeDriver};
for (WebDriver driver:drivers){
...test goes here.....
}
The problem with this method is that each test you run will have to have that for loop, and they all will create their own drivers.
Solution 2: You could have a central method call each of your tests. It would look something like this:
public void runTests(){
...create your drivers here (and the array)...
for (WebDriver driver: drivers){
runFirstTest(driver);
runSecondTest(driver);
}
}
public void runFirstTest(driver){
...code using driver goes here....
}
This solves the problem of having a for loop and creating driver instances in every test, but now, whenever you write a new test, you have to add it to this for loop.
Solution 3: Another solution exists, using a testing framework. The two most popular are TestNG and JUnit. I'm going to assume all of your tests are in the same class, but if you have multiple classes, you will want to have only 1 class have the #DataProvider
#DataProvider(name = "drivers")
public provideDrivers(){
...create drivers here...
return new Object[][]{{firefoxDriver},{chromeDriver},....};
}
#Test(dataProvider = "drivers")
public runTest(WebDriver driver){
...do stuff with driver here...
}
This solution will run every method that has #Test(dataProvider = "...") once for every driver you pass in. More information is here
If you have questions, feel free to comment. I will respond.

Related

I have requirement to run my automated test cases continuously. Whats the best approach?

I have to run my automated test scripts of web application, continuously regardless of the status of result.please suggest me the best way/tool other than Jenkins.We are using Java,TestNG and selenium web driver.
If you're using any Linux or Mac system you can set a cronjob to schedule an execution of a command (in this case your tests).
https://www.ostechnix.com/a-beginners-guide-to-cron-jobs/
It's as easy as it can get if it fits your needs.
If you want to repeat a single void, you can change the invocationCount to achieve the number of times at TestNG
#Test(priority = 1, invocationCount = 100)//run 100
public void test1() {
}

Flow of automation tests with an if else logic in Java

In automating the passing of levels in a game, I have several user groups, which are all logging in the game with a method, that accepts the input for username and password, but receive a different number of unlocked levels, depending on the user group (each user has different levels available in the game).
In the process of testing the passing of all the levels, I want to determine during the test at the end of each level if the user has the next one unlocked, and either continue the test or finish it successfully.
I've read about if else implementations with selenium and I am currently using a method like this:
public boolean isElementExisting(WebElement element){
try {
wait.until(ExpectedConditions.elementToBeClickable(element));
} catch (Exception e) {
return false;
}
return true;
}
and using and if logic like so in the test:
if (isElementExisting(level3Button) == false) {
driver.quit();
}
- rest of the tests follow here.
When using a driver.quit(); the test automatically fails. The desired behavior I am searching for is for the test to pass in the if statement (what could be used instead of a driver.quit(); method)?
I could just fit all the code for testing the further levels in separate nested if/else statements but that would be troublesome, currently looking for a more practical solution, like succeeding the test at a certain point.
A test should be static in the sense that it should have a known outcome.
As a result, the way the test is structured and written should follow that logic.
Given what was described above, I would write a test something like this:
login.asUser(username,password);
// additional logic in here
assertTrue(page.userHasLevelUnlocked("level3"));
then the method
public boolean userHasLevelUnlocked(String level){
switch(level)
case "level3":
if(isElementExisting(level3button){
return true;
} else {
return false
}
}
or something along those lines
Thank you for you answer. I understand the concept of a static test, with the addition that a test should not have a "known" outcome, but more that it should have an "expected" outcome, which should be matched, in the sense that it tests something to verify its functionality.
The switch case is a valid scenario, quite frankly I don't see what happens after the assertion fails in the posted example (the test will fail as well).
The solution I implemented is to determine if the user has the next level unlocked at the end of the previous one with a method similar to this:
public void isElementExistingAlternateResult(WebElement element) {
boolean isElementFound = true;
try {
wait.until(ExpectedConditions.elementToBeClickable(element));
} catch (Exception e) {
isElementFound = false;
}
if (isElementFound == true) {
System.out.println("test is continued...");
} else {
Reporter.getCurrentTestResult().setStatus(ITestResult.SUCCESS);
System.out.println("next level not unlocked.");
}
That way, only if the next available level is not found, the test will determine this real time and it will stop and pass at this exact point. Note that this is alternating the result of a otherwise failed test case with the TestNG Reporter class in:
Reporter.getCurrentTestResult().setStatus(ITestResult.SUCCESS);
The downside - this makes the test unable to test the functionality of having different amount of levels unlocked for different users, as no matter of the number of levels unlocked it will test them and pass, but that's something better of not automated.
The upside - it's super simple and works great for a test case of about 500 steps (makes only a few of them "dynamic").

Run each cucumber test independently

I'm using cucumber and maven on eclipse and what I'm trying to do is run each test independently. For example I have a library system software that basically allows users to borrow books and do other stuff.
One of the conditions is that users can only borrow a max of two books so I wrote to make sure that the functionality works. This is my feature file:
Scenario: Borrow over max limit
Given "jim#help.ca" logs in to the library system
When "jim#help.ca" order his first book with ISBN "9781611687910"
And "jim#help.ca" orders another book with ISBN "9781442667181"
And "jim#help.ca" tries to order another book with ISBN "1234567890123"
Then jim will get the message that says "The User has reached his/her max number of books"
I wrote a corresponding step definition file and every worked out great. However, in the future I want to use the same username ("jim#help.ca") for borrowing books as though jim#help.ca has not yet borrowed any books. I want each test to be independent of each other.
Is there any way of doing this...maybe there's something I can put into my step definition classes such as a teardown method. I've looked into it but I couldn't fine any solid information about it. If there's a way please help me. Any help is greatly appreciated and I thank you in advance!
Yes, you can do setups and teardowns before and after each scenario, but it's not in the step definition file. What you want to use are hooks.
Hooks run before or after a scenario and can run before/after every scenario or just the ones you and #tag to, for example:
#remove_borrowed_books
Scenario: Borrow over max limit
Unfortunately I have only used cucumber with ruby not java so I can't give you step-by-step instructions, but this should tell you what you need to know https://zsoltfabok.com/blog/2012/09/cucumber-jvm-hooks/
You can use the "#After" hook to achieve this as #Derek has mentioned using for example a Map of books borrowed per username:
private final Map<String, Integer> booksBorrowed = new HashMap<>();
#After
public void tearDown() {
booksBorrowed.clear();
}
#Given("...")
public void givenUserBorrowsBook(String username) {
booksBorrowed.put(username, booksBorrowed.containsKey(username) ? booksBorrowed.get(username) + 1 : 1);
....
}
Or the "#Before" hook to perform the cleanup before each scenario is executed, which is the option I would recommend:
private Map<String, Integer> booksBorrowed;
#Before
public void setUp() {
booksBorrowed = new HashMap<>();
}
If you are planning to run scenarios in parallel then the logic will be more complex as you will need to maintain the relationship between the thread executing a particular scenario and the usernames used on that thread.

Index not Found Exception

So, back again
I have a JHipster generated project which uses an elasticsearch java client embedded in spring boot.
I have recently done some major changes to the datasets since we've been migrating a whole new bunch of data from different repositories
When deploying the application it all works fine, all SearchRepositories are loaded with no problem and all search capabilities roll smooth
The issues come when running from the test environment. There have been no changes what so ever to the application-test.yml file nor to the elasticsearch java config file.
We have some code which updates the indices and I've run it several times, it seems to update the clusters indices just fine, but where I'm suffering is in the target folder, it just won't create the new indices
There are 12 indices that I cannot get in to the target folder when running in test mode, however, only 5 of them fail in their ResourceIntTest because of the error mentioned in the title
I don't want to fill this post with hundreds of irrelevant lines of code, so suffice for now to include the workaround that helps test not to fail:
When in the initTest of the 5 failing test cases, if I write the following line (obviously changing the class name in each different case):
surveyDataQualitySearchRepository.save(surveyDataQualityRepository.findAll());
Then the index will create itself and the testcase will not fail, however this shouldn't be necessary to do manually, it should be created when the resetIndex method in the IndexReinitializer class is called upon deployment
resetIndex:
#PostConstruct
public void resetIndex() {
long t = currentTimeMillis();
elasticsearchTemplate.deleteIndex("_all");
t = currentTimeMillis() - t;
logger.debug("ElasticSearch indexes reset in {} ms", t);
}
Commenting this piece of code also allows all indices to be loaded, but it should not be commented as this serves as an updater for the indices, plus it works fine in an old version of the application which is still pointing to the old dataset
All help will be very welcome, I've been on this almost a full day now trying to understand where the error is coming from, I'm also more than happy to upload any pieces of code that may be relevant to anyone willing to help here.
EDIT To add code for the indices rebuild as requested via comments
#Test
public void synchronizeData() throws Exception{
resetIndex();
activePharmaIngredientSearchRepository.save(activePharmaIngredientRepository.findAll());
countrySearchRepository.save(countryRepository.findAll());
dosageUnitSearchRepository.save(dosageUnitRepository.findAll());
drugCategorySearchRepository.save(drugCategoryRepository.findAll());
drugQualityCategorySearchRepository.save(drugQualityCategoryRepository.findAll());
formulationSearchRepository.save(formulationRepository.findAll());
innDrugSearchRepository.save(innDrugRepository.findAll());
locationSearchRepository.save(locationRepository.findAll());
manufacturerSearchRepository.save(manufacturerRepository.findAll());
outletTypeSearchRepository.save(outletTypeRepository.findAll());
publicationSearchRepository.save(publicationRepository.findAll());
publicationTypeSearchRepository.save(publicationTypeRepository.findAll());
qualityReferenceSearchRepository.save(qualityReferenceRepository.findAll());
reportQualityAssessmentAssaySearchRepository.save(reportQualityAssessmentAssayRepository.findAll());
//rqaaQualitySearchRepository.save(rqaaQualityRepository.findAll());
rqaaTechniqueSearchRepository.save(rqaaTechniqueRepository.findAll());
samplingTypeSearchRepository.save(samplingTypeRepository.findAll());
//surveyDataQualitySearchRepository.save(surveyDataQualityRepository.findAll());
surveyDataSearchRepository.save(surveyDataRepository.findAll());
techniqueSearchRepository.save(techniqueRepository.findAll());
tradeDrugApiSearchRepository.save(tradeDrugApiRepository.findAll());
tradeDrugSearchRepository.save(tradeDrugRepository.findAll());
publicationDrugTypesSearchRepository.save(publicationDrugTypesRepository.findAll());
wrongApiSearchRepository.save(wrongApiRepository.findAll());
}
private void resetIndex() {
long t = currentTimeMillis();
elasticsearchTemplate.deleteIndex("_all");
t = currentTimeMillis() - t;
logger.debug("ElasticSearch indexes reset in {} ms", t);
}
Please try to update to the latest version of spring-data-elasticsearch

How to run browsers concurrently/simultaneously with Selenium Grid to search a list of strings in parts (in Java)

I want to be able to take a list of Strings, split the list into parts, and have each browser running search a part of the list (i.e. browser1 does 1/5, browser2 does 2/5...) in let's say Google (I happen to be using Firefox).
How would I go about doing this using Selenium Grid. I have it set-up, and I know how to register the hub and nodes to that hub, but if it helps your explanation or the solution involves a different kind of instantiation, then let me know. I think it would help other users reading this to just have that thrown in...
A step-by-step solution would satisfy me though. I just can not get Selenium to function the browsers concurrently, even with 2 nodes. Is it required that I use TestNG or Mable or something (I'm not familiar with these)? I wish to one day have this program developed into a Win32 application (in C++/C#), so it can't just run in a "test suite" if I can't encapsulate it later for distribution.
EDIT:
Here's the framework of what I mean. Obviously it will not accomplish the task, as I am asking the question now. I don't know if this would require multiple drivers or even multiple copies of the same program running in memory, so I will comment appropriately in the code. This is in no way yet made to be concurrent-just the task I wish to make concurrent on the grid.
public void beginSearch(){
ArrayList<String> searchTerms=new ArrayList<String>();
//Pretend searchTerms is full of 100 Strings!
//Create a new instance of the Firefox Driver
capabilities=DesiredCapabilities.firefox();
//Let's say I have one WebDriver object for now
try{
driver=new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), capabilities);
}catch (MalformedURLException e){
e.printStackTrace();
}
//Go to Google
driver.get("http://www.google.com");
for(int i=0; i<searchTerms.size(); i++){
/*I put the findElement() inside the loop due to experience with it
*not being able to interact with the same element on a different page when
*the URL changes. I think it's due to XPath use internally in the WebElement
*class. Ignore this for now.
*/
element=driver.findElement(By.name("q"));
element.sendKeys(searchTerms.get(i));
element.submit();
}
driver.quit;
}
/*Let's say for the hell of it this is all I wanted to do-how could I make it perform
*this concurrently on the Grid!?
*/
Interesting... so as far as I know making the connection to the WebDriver in code is no different than connecting directly to the WebDriver, in terms the actual code you use. You can connect to an individual node in the same manner in which you connect to the grid. The grid is simply responsible for determining which node to hand off the test to and queue requests when there aren't any available nodes. You should be able to connect the Selenium Grid2 using a WebDriver on an individual thread without any problems, so long as you're not sharing references. I think the general rule is one WebDriver per thread.
https://code.google.com/p/selenium/wiki/FrequentlyAskedQuestions
You don't absolutely need something like TestNG. TestNG contains a lot of nice functionality like ways of providing large data sets, advanced logging capabilities, test suites, etc.
http://en.wikipedia.org/wiki/TestNG
Here is an incredibly basic idea. Each test is run on it's own thread with each instance of the WebDriver running on it's own thread. I've not tested this code.
public class Tests {
public static void main(String[] args) {
for(int threadCount = 0; threadCount<5; threadCount++) {
new Thread(new Runnable() {
public void run() {
//Create a new instance of the Firefox Driver
capabilities=DesiredCapabilities.firefox();
//Let's say I have one WebDriver object for now
try{
driver=new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), capabilities);
}catch (MalformedURLException e){
e.printStackTrace();
}
//Go to Google
driver.get("http://www.google.com");
//Quit Driver
driver.quit;
}
}).start();
}
}
}
I wouldn't recommend trying to manage your threads in this fashion, but trying this might reveal problems:
WebDriver driver = ThreadGuard.protect(
new RemoteWebDriver( "http://localhost:4444/wd/hub", capabilities) );
I use TestNG to manage my threads and so I don't need to worry much about this stuff.

Categories

Resources