I am automating a test, and there are some steps where I need to repeat the 'Enter' key many times, so I am trying to create a loop where 'Enter' is pressed until an object becomes available, or visible.
I already tried quite a few different ways to do it, but it never works, normally the while statement or the if statement breaks without the condition being broken.
On the following example, I am creating object x and object y. I want to repeat y until I get to a window where x is available.
Also here are a few of my failed attempts.
TestObject x = findTestObject('path/1')
TestObject y = findTestObject('path/2')
while (true) {
WebUI.click(y)
if (WebUI.verifyElementPresent) break
}
//
//while (WebUI.verifyElementNotPresent(x, 10)) {
// WebUI.click(y)
//}
//while(true) {
// WebUI.click(y)
// if(WebUI.verifyElementVisible(x))
// WebUI.click(y)
//}
Example of what I am trying to avoid.
WebUI.click(y)
WebUI.click(y)
WebUI.click(y)
WebUI.setText(x, '1')
and there are some steps where I need to repeat the 'Enter' key many times, so I am trying to create a loop where 'Enter' is pressed until an object becomes available, or visible
It sounds like that field that "Enter" is being pressed on, is a search field, and that "object becoming available or visible" is a search result...
As for your retry logic, take a look at my answer on the Katalon Studio forum:
public class ActionHandler {
public static void HandleRetryableAction(Closure onAction, Closure onDone, long timeOut) {
long startTime = System.currentTimeSeconds();
while (System.currentTimeSeconds() < startTime + timeOut) {
try {
onDone(true, onAction());
return;
} catch (Exception ex) {
onDone(false, ex);
}
}
}
}
You should use this custom keyword like this:
ActionHandler.HandleRetryableAction({
WebUI.sendKeys(findTestObject('path/2'), // you should REALLY name this something better...something more meaningful...
Keys.ENTER.toString());
final TestObject firstSearchResult = findTestObject('path/1'); // again, fix the naming please!!
// we're waiting on search result to **disappear**, in order to squash any flakiness that comes from the next step...
WebUI.waitForElementNotPresent(firstSearchResult,
1,
FailureHandling.OPTIONAL);
return WebUI.waitForElementPresent(firstSearchResult,
5);
}, { boolean success, _ ->
if (!success) {
// take additional actions, such as refreshing the page, clicking some refresh widget, ...
}
},
15, // I set it to 3 times the wait time specified by Mate Mrse, for good measure
)
Take note of three things here...
1.) It's WebUI.sendKeys() to...well...send the keys. Also, the String argument is the stringification of org.openqa.selenium.Keys.ENTER .
2.) We are using the WebUI.waitForElementPresent() here. This is built-in keyword.
3.) I don't see any action we're taking if the result is NOT present after Enter, except spamming Enter. You should spell out what we should do in that case.
In the absence of any onRetry logic, I think your idea to use loop, and my idea to use ActionHandler, is overkill.
Please respond back with your full use case here, and maybe some screenshots of or link to the AUT itself, and I can adjust this answer to that!
You can use WebUI.verifyElementPresent() method like this (Note: you are missing the parenthesis in your example. Also, timeout is required):
condition = true
while (condition) {
WebUI.click(y)
if (WebUI.verifyElementPresent(x, 5)) {
condition = false
}
}
WebUI.setText(x, '1')
Related
I am learning java and so far I have created a password check using if statements. However I inserted my working String check into a while loop and added Thread.sleep(3000); for a 3 second delay, however once I completed that my GUI just keeps lagging and freezing on one page as if the button was pressed. Can somebody please show me how to make a working example of a code with a String check and after a certain amount of tries a delay to stop the user from trying again?
(here is what I have:)
//var declaration
boolean match = false;
String1 = "hi";
String2 = (I know this is not code but just to omit some code:) userInput
int time = 3000;
int attempt = 0;
//check
while(!match && attempt < (maximumTries+1)){
if(String1.equals(String2)){
System.out.print("match");
}
else if(attempt < 11){
attempt++;
System.out.println("Failed:" + attempt);
}
else{
attempt++;
System.out.println("Please try again later you have:" + attempt + "failed attempts");
try{
Thread.sleep(time);
}
catch(InterruptedException ex) {
Logger.getLogger(PasswordEntry.class.getName()).log(Level.SEVERE, null, ex);
}
time = time + 1000;//1 second more every time
}
}
your code is doing an infinite loop once the first attempt does not match.
in each of the iterations of your loop there is no change at all, aside from incrementing the counter. so the counter just increases forever (with some delays in between).
it seems the reasoning behind your code was that String2 got updated with user input inside the loop not outside. This way, on each iteration you would have a different String2 to compare against.
That's your issue, not the way you delay between attempts (that for sure can be improved in any case).
You should avoid using the Thread.sleep option since it completely freezes the main thread. You could also try creating another thread, which will be frozen and later in gives a callback to the main one. For example through a boolean variable. I'd also agree on the timer solution mentioned by BladeMight.
I have made a for loop with a nested if block. On exit of the loop I want the object to perform an action by calling a method. At the moment I am struggling to find how to do this. Could anyone make any suggestions?. Below is the code I have made.
public void goLoop()
{
for (int i = 1; i <= getAmountOfLoops(); i++ )
{
if (getPosition() => 25)
{
this.setPosition(4);
}
else
{
this.keepLooping();
this.setTotalAmountOfLoops(getTotalAmountOfLoops() + 2);
}
jump(); // Do I put the action to perform on exit of loop here?
}
Just call it after the loop:
for (... ) {
}
action();
BTW change getPosition() => 25 to getPosition() >= 25.
Note: It's always better to be aware of the logic of your program before you start coding, however if you start coding and suddenly encounter a trivial situation like this, just give it a try! and check if it produces the desired result or not.
So I have a loop that is wrapped around a loop and an if statement. When running the program however, it gets out of the inner loop (as planned) and then it fails the if statement (also as planned), resorting to the else statement which is a simple print.
What I /wanted/ to happen was have it then (in the case the if fails), restart to the original inner loop--hence the outer loop. But instead, after it fails the if statement, it begins to loop "phrase2" over and over.
Here is the simplified code:
int x = 1;
int y = 1;
int i = 0;
while(i == 0)
{
while(<condition that is false>)
{
System.out.println("phrase1");
a = input.nextInt();
b = input.nextInt();
}
if(<condition that is false>)
{
i = 1;
}
else
{
System.out.println("phrase2");
}
}
Thanks for your help regardless!
EDIT:
For the sake of emphasis...
What happens:
Infinite loop spewing "phrase2".
What I wanted:
After the else is executed, I wanted to be brought into the inner loop again.
Whatever condition you're using in the inner loop, just make sure it's true.
else
{
System.out.println("phrase2");
// SET THIS TO TRUE: <condition that is false>
}
This way, the inner loop will trigger again.
Your control never enters the below if statement
if(<condition that is false>)
{
i = 1;
}
You might need to adjust your conditions so that it comes into the above if block. Introduce a System.out.println inside if statement to debug
It looks like you have some code that you probably want to run once, unless something went wrong, and then you want to go back and retry. The idiom I usually use for that looks like
boolean needToRetry;
do {
needToRetry = false;
// do whatever
if (somethingWentWrong) {
needToRetry = true;
// set this at any point where you find you will need to go back
}
} while (needToRetry);
The important thing is that you need to reset your flag (needToRetry) at the beginning of the loop, each time. (P.S. There are other ways to do this using break or continue, although I personally don't like using continue.)
I am trying to validate some text files. In the front end i am using JTextarea, The below method is called on every time the user enter 'Enter' key. If the file is too big,say 5000 lines and if the user enters many times 'Enter' key then, i am getting unexpected results, like even if the line is valid, it shows it as invalid.
Is there any thing to do with sleep, should i have to increase the sleep time or something else has to be done? Any ideas will be helpful
private TreeSet validate(int curLine, TreeSet errorSet) {
int increment = 0;
int nextLine = 0;
if (curLine == lines.length || errorSet.size() != 0) {
return errorSet;
} else {
String line = lines[curLine];
//validation starts. After validation, line is incremented as per the requirements
increment = 1 //As per requirement. Depends on validation results of the line
if (increment > 0) {
try{
Thread.currentThread().sleep(100);
}catch(Exception ex){
System.out.println(ex);
}
nextLine = (curLine + increment);
validate(nextLine, errorSet);
}
}
return errorSet;
}
I wouldnt look at making the sleep time any longer/shorter. Instead, I would consider doing a better time at marshalling the trigger to validate. Is there any reason to allow the input of a validation request while one is in progress? if not, i would look at blocking the call to validate while a current process is still not complete.
If you think that multiple validations should be able to occur in tandem, I would then look to the creation of a thread pool for these actions. Testing my determine how many threads can concurrently run, and therefore determine the size of your threadpool. At this point, system memory may also play an important point, so you may want to look at those statistics while testing as well.
I've got a bit of an issue with my little program.
I have a JOptionPane asking for a number, and if that number is less than 10, a loop that just continues on and on forever doing what's in it, keeping on asking for numbers. Inside that loop, I call a method, with an int as parameter. In the method, I need to (without altering any of the code in the class that calls the method) find out whether the number I entered is less than 1. If it is, I need to call on another method. That bit's done.
But! The mainloop keeps rolling, so it keeps doing the other stuff in the loop. I need to stop it from doing that, so in the if-statement in the method I need to break that specific iteration of the loop the method is in, and make it go on to a new iteration of the same loop, asking for a new number.
The first class (example):
number=Integer.parseInt( JOptionPane.showInputDialog( "bla bla" ) );
while (number !=- 10) {
themethod(number);
blah
blah
...
}
The called method (example):
public void themethod(int number) {
if (number<1) {
call the other method
break the iteration im in
}
There are a number of things you can do here. Ultimately what you do should depend on your coding style and what you are trying to accomplish.
Option 1 would be some variation of:
for (;;)
{
int number = /* ... */;
myMethod(number);
if (number == -10)
break;
}
You might say, rather subjectively and depending on circumstances, that this is bad, because knowledge of the termination condition is contained in the loop rather than the method doing the "real work". Maybe for your loop that's OK. Maybe in other circumstances (or perhaps with other programmers? This is very much a matter of taste.) you might want to make myMethod make that decision. In general my own personal taste usually leans towards not having scenario knowledge be distributed throughout various methods in source, but in one place.
So most of what I'll write from here on will be how to make myMethod make the decision about whether or not to terminate.
Option 2 - myMethod returns a boolean indicating we should terminate:
for (;;)
{
int number = /* ... */;
if (myMethod(number))
break;
}
boolean myMethod(int number)
{
// TODO - do stuff
return number == -10;
}
But you might say that myMethod already wants to return some other type. I come from very much a C background so the idiom I'm most used to would be the "out parameter". Leading me to option 3:
Option 3 - Out parameter lets caller decide to terminate:
public class CancelIndicator
{
public boolean shouldCancel;
};
CancelIndicator cancel = new CancelIndicator();
while (!cancel.shouldCancel)
{
int number = /* ... */;
myMethod(number, cancel);
}
int myMethod(int number, CancelIndicator cancel)
{
// TODO - do stuff.
cancel.shouldCancel = (number == -10);
return /* ... */;
}
Or maybe you're more a fan of exceptions:
Option 3:
public class CancellationException extends Exception
{
}
try
{
for (;;)
{
int number = /* ... */;
myMethod(numberl);
}
}
catch (CancellationException ex)
{
}
void myMethod(int number) throws CancellationException
{
// TODO - do stuff.
if (number == -10)
throw new CancellationException();
}
As you can see there are a number of options. I'm sure one could spend a whole day talking about different ways to do it. Here is my sample of idioms I have seen - I'll warn you that it's been some time since I've done much in Java so I might not write the most idiomatic code here. :-)
Add a return value indicating that the while should break:
public boolean themethod(int number) {
if(number<1) {
call the other method
return true;
}
return false;
}
Then:
while(number !=-10) {
if(themethod(number)) break;
bla
bla
...
}
Edit: If you can't change the while code, throw an exception from the method:
public void themethod(int number) {
if(number<1) {
call the other method
throw new RuntimeException("Negative Number");
}
}
Wait, so did I get this straight? You have a loop that asks for a number, does something if the number is not -10, and otherwise breaks?
If so, look at this:
while(true) {
number=Integer.parseInt( JOptionPane.showInputDialog( "bla bla" ) );
if(number == -10) {
break;
}
themethod(number);
}
Otherwise, if this is not the case, and you want to break in two cases, the -10 case and the method is false case, you can do this:
Change your method to return a boolean. If it's true, then it doesn't want to break. If it's false then it wants to break, then do this:
while(true) {
number=Integer.parseInt( JOptionPane.showInputDialog( "bla bla" ) );
if(number == -10) {
break;
}
if(!themethod(number)) break;
}
If you really can't edit the loop, then just throw an exception from the method! That will exit your entire program, though. I don't see any other possible way of doing this, however.
Without a return value for themethod(int) and without changing the other class's code, this isn't possible since as it is, there is no return communication. You'll have to change both; it can't be done without changing the logic in the loop.