I have a function that calls a test on each object. I want to be able to retest if the current test fails.
foreach (TestObject test in Tests)
{
test.RunTest()
}
//This is in the TestObject class
RunTest()
{
if (failure)
{
//Want to be able to run RunTest() again without interrupting the foreach loop.
}
}
You guys like too much code...
for (var tryCount = 0; tryCount < 3; tryCount++)
if (test.RunTest())
break;
... oh I thought of an even shorter version... but it's not as clean ...
for (var tryCount = 0; !test.RunTest() && tryCount < 3; tryCount++);
If you want reuse then something like this...
static bool RunTest(Func<bool> testCase, int maxRetry)
{
for (var tryCount = 0; tryCount < maxRetry; tryCount++)
if (testCase())
return true;
return false;
}
// usage
var testResult = RunTest(test.RunTest, 3);
// or even...
var testResult = RunTest(
{
try {
return test.RunTest();
} catch (Exception ex) {
Debug.WriteLine(ex);
return false;
}
}, 3);
For both answers above, the solutions will result in RunTest() running forever if the failure is legitimate (i.e. not a transient failure, which I can only guess is what you're hitting). You may consider doing one of the loops above, but instead keep a count of how many failures and bail out once that threshold is reached. Something like:
int FailureThreshold = 3;
foreach (TestObject test in Tests)
{
int failCount = 0;
while (failCount < FailureThreshold)
{
if (test.RunTest())
{
break;
}
else
{
failCount++;
}
}
}
You should also consider keeping statistics for how many times you need to loop in order to pass. This could be a great indicator of test stability.
There are several ways you could go about doing this, depending on why exactly you want to do this. You could:
1) Have RunTest() return boolean for success or failure, and then:
foreach (TestObject test in Tests)
{
while(!test.runTest(){}
}
2) Use a while inside of RunTest():
RunTest()
{
while(true)
{
...test stuff...
if(failure)
continue;
else
break;
}
}
foreach (TestObject test in Tests)
{
test.RunTest()
}
//This is in the TestObject class
RunTest()
{
//set it to failure or set variable to failure
while (failure)
{
//do the test
//if using variable set it to failure if it failed, success if it succeeded
//will keeping going through the while statement until it succeeds or you cut it off another way
}
// has succeeded
}
Related
I have several variations of the following code within methods that are being used for Selenium testing (waits for certain events before returning) and I would like to refactor it and make it reusable so I have the logic controlling the delay & try/catch as a generic method but be able to swap in and out conditions depending on situation.
Is there an easy way to achieve this?
Code:
for (int second = 0; second <= 10; second++)
{
try
{
// bit that needs to vary
matchedAddresses = driver.FindElements(By.ClassName("addresslookup"));
if (matchedAddresses.Count > 0)
{
break;
}
}
catch (Exception)
{
}
Thread.Sleep(1000);
}
return matchedAddresses.Count;
You want function that takes argument of something like Func<int> - method that returns number of elements (or enumerable Func<IEnumerable<sometype>>)
public int GetCountOfElementsWithWait(Func<int> test)
{
.....
var count = test();
....
}
Seems a bit too obvious, but would this work?
public int GetCountOfElementsByClassName(string className)
{
for (int second = 0; second <= 10; second++)
{
try
{
// bit that needs to vary
matchedElements = driver.FindElements(By.ClassName(className));
if (matchedElements.Count > 0)
{
break;
}
}
catch (Exception)
{
}
Thread.Sleep(1000);
}
return matchedElements.Count;
}
New to programming and reading a how to book. Question is about loops. I have the following code:
public bool DoThisJob(string job, int numShift) {
if (!string.IsNullOrEmpty(currentJob))
return false;
for (int i = 0; i < jobsICanDo.Length; i++) {
if (jobsICanDo[i] == job) {
currentJob = job;
this.shiftsToWork = numberOfShifts;
shiftsWorked = 0;
return true;
}
return false;
If the currentJob string is not empty then return false or return true? There is no else statement so how do we know what to do if it is true?.
Next run a for loop and again is the for loop ran because it returned false or true? Last run an if statement which is self explanatory.
There is no else because of the "return" statement. It immediately aborts execution of the function and returns to the calling function. You could write it with an else and it will function the same.
There is no else statement so how do we know what to do if it is true?.
in an if ... else (or classically called if .. then .. else) construct else if optional and in its absence it would fall through to the next statement outside the if block, in this case its the for statement
Your above function can be equivalently though to be similar to
public bool DoThisJob(string job, int numShift) {
if (!string.IsNullOrEmpty(currentJob))
return false;
else {
for (int i = 0; i < jobsICanDo.Length; i++) {
if (jobsICanDo[i] == job) {
currentJob = job;
this.shiftsToWork = numberOfShifts;
shiftsWorked = 0;
return true;
}
return false;
}
If the currentJob string is null then the if statement won't be run, and it will fall through to the for loop.
If the conditions in the for loop trigger it to return true then the method returns true and the last return is never reached.
If the for loop doesn't return true it will fall onto the last line and the method will return false.
A return statement stops the execution of the function at that point and returns control to the calling procedure.
public bool DoThisJob(string job, int numShift) {
if (!string.IsNullOrEmpty(currentJob))
return false; // If it is not empty then function call returns from this statement
// Else, flow control falls through and below code is executed
for (int i = 0; i < jobsICanDo.Length; i++) {
if (jobsICanDo[i] == job) {
currentJob = job;
this.shiftsToWork = numberOfShifts;
shiftsWorked = 0;
return true;
}
return false;
}
I hope, this clarifies the question.
Your function can be simplified as follows without a loop;
public bool DoThisJob(string job, int numShift) {
if (!string.IsNullOrEmpty(currentJob) || !jobsICanDo.Contains<string>(job))
{
//if currentJob NOT null/empty OR
//job is not in the jobsICanDo[] array
return false;
}
else
{
currentJob = job;
this.shiftsToWork = numberOfShifts;
shiftsWorked = 0;
return true;
}
}
I searched SO and found some posts, but could not get them to work.
Question: How would I loop to the next item in my List Collection (custLoginHist[1] etc)?
List<eCommCustomer.oCustomer> custLoginHist = new List<eComm.oCustomer>();
eCommCustomerDAL.GetCustomerPrevLogin(custLoginHist, oCust);
if (custLoginHist.Count > 0)
{
eCommSecurityFactory oSecFactory = new eCommSecurityFactory();
if (oCust.CustHash == oSecFactory.CreateHash(custLoginHist[0].CustSalt, custLoginHist[0].CustHash))
{
//Password has been used before;
return false;
}
else
{
// Valid password;
return true;
}
}
return true;
}
foreach(eCommCustomer.oCustomer cust in custLoginHist)
{
//Do something with cust here.
}
OR:
for(int i = 0; i != custLoginHist.Count; ++i)
{
eCommCustomer.oCustomer cust = custLoginHist[i];
//Do something with cust here.
}
In this case, we want to return false for any single match, and true otherwise, so:
foreach(eCommCustomer.oCustomer cust in custLoginHist)
if(oCust.CustHash == oSecFactory.CreateHash(custLoginHist[0].CustSalt, custLoginHist[0].CustHash)
return false;
return true;//if we reached here, no matches.
This is a bad idea though, because you've made breaking into the system easier. If I try to set my password to something, and you refuse, I now know that one of your users uses that password. You are much better off letting this case happen, though you should perhaps be blocking some of the more likely offenders ("password", "password1", etc) with a quality check.
List<eCommCustomer.oCustomer> custLoginHist = new List<eComm.oCustomer>();
eCommCustomerDAL.GetCustomerPrevLogin(custLoginHist, oCust);
foreach (var custLogin in custLoginHist)
{
eCommSecurityFactory oSecFactory = new eCommSecurityFactory();
if (oCust.CustHash == oSecFactory.CreateHash(custLogin.CustSalt, custLogin.CustHash))
{
//Password has been used before;
return false;
}
}
return true;
Try something like this, maybe you have to customize your return statements but it should give you an insight how it works.
foreach(var item in yourList)
{
//Iterate;
}
If you want break , you can use : break;
If you want finish you can use : continue;
List<T> implements IEnumerable<T>, so you can just use foreach or if you to be able to edit T in the loop, you can use for.
foreach(var item in custLoginHist)
{
}
Or
for (int i = 0; i < custLoginHist.Count; i++)
{
}
Then if you need to exit out of the loop before it is completed (such as if you have a condition that is true, you can just use break; to exit the loop, or you can return from a loop too if you want to return a value.
You can you loop for this. For example foreach or for:
foreach (var custLogin in custLoginHist)
{
eCommSecurityFactory oSecFactory = new eCommSecurityFactory();
if (oCust.CustHash == oSecFactory.CreateHash(custLogin.CustSalt, custLogin.CustHash))
{
//Password has been used before;
return false;
}
else
{
// Valid password;
return true;
}
}
List<eCommCustomer.oCustomer> custLoginHist = new List<eComm.oCustomer>();
eCommCustomerDAL.GetCustomerPrevLogin(custLoginHist, oCust);
return custLoginHist.Select(c=>oSecFactory.CreateHash(c.CustSalt,c.CustHash))
.Any(x=>x==oCust.CustHash)
hey guys m running into a problem, i have a forloop n in that i call a function, and in that function i have a if condition, i want to skip 1 loop if condition gets true, for this problm i was thinkin' to use goto statement but as i read in many forums that goto statement is an evil... can it be solved without using goto statement, ne ideas i dn't want to use 'goto'
for(int i=0;i<gridview.rows.count-1;i++)
{
//some operation;
aFunction(param1,param2);
}
public void aFunction(param1,param2)
{
//some operation;
if (!Regex.IsMatch(RechargeText, "successfully"))
{
RechargeStatus = "Failed";
Program.sp.SoundLocation =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) +
"/aimlife_error.wav";
Program.sp.Play();
}
else if (Regex.IsMatch(RechargeText, "Processing") || Regex.IsMatch(RechargeText, "Not"))
{
// here i need to skip the Loop
}
else
{
Program.sp.SoundLocation =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) +
"/aimlife_success.wav";
Program.sp.Play();
}
Program.StatusMessage = "Recharge Successful";
TextFill();
}
Actually there are some error list that are accepted errors, so i dn't need to update that in db, So my TextFill(); function shud not run for accepted errors
Snippet Edited
Simple, have the method return a bool. Then you can do:
for(int i=0;i<gridview.rows.count-1;i++)
{
//some operation;
if (aFunction(param1,param2)) break;
}
goto won't help you anyway. Basically you can't continue from a different method at all. The only simple way you can keep roughly your current flow is something like this:
bool shouldSkipNext = false;
for (int i = 0; i < gridview.Rows.Count - 1; i++)
{
if (shouldSkipNext)
{
shouldSkipNext = false;
continue;
}
// some operation
shouldSkipNext = aFunction(param1, param2);
}
public bool aFunction(param1,param2)
{
if (abc)
{
return true;
}
// Other stuff
return false;
}
Note that this will skip the entirety of the next iteration of the loop - which isn't the same as just continue. If you have more code after the call to aFunction and you want to skip that (which is the equivalent of continue) then it's simpler:
for (int i = 0; i < gridview.Rows.Count - 1; i++)
{
// some operation
if (aFunction(param1, param2))
{
continue;
}
// Other stuff which will sometimes be skipped
}
All you want to do is skip executing the TextFill() function when the condition if (Regex.IsMatch(RechargeText, "Processing") || Regex.IsMatch(RechargeText, "Not")) is true, thats all right?
You can simply return at that if condition, which will work out as you want:
else if (Regex.IsMatch(RechargeText, "Processing") || Regex.IsMatch(RechargeText, "Not"))
{
return;
} .... // rest of the code as it is
now when the above condition works out as true it will return to the for loop and go with the next iteration and so on...
Cheers
for(int i=0;i<gridview.rows.count-1;i++)
{
//some operation;
if (!aFunction(param1,param2)) continue;
}
public bool aFunction(param1,param2)
{
//some operation;
if (!Regex.IsMatch(RechargeText, "successfully"))
{
RechargeStatus = "Failed";
Program.sp.SoundLocation =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) +
"/aimlife_error.wav";
Program.sp.Play();
}
else if (Regex.IsMatch(RechargeText, "Processing") || Regex.IsMatch(RechargeText, "Not"))
{
Program.StatusMessage = "Recharge Successful";
TextFill();
return false;
// here i need to skip the Loop
}
else
{
Program.sp.SoundLocation =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) +
"/aimlife_success.wav";
Program.sp.Play();
}
Program.StatusMessage = "Recharge Successful";
TextFill();
return true;
}
If your code as posted is exactly how it is, then you could simply return, as the loop has no other operations.
No, it can not be solved with a goto... thankfully.
There is nothing that you can do inside the method that will change the control flow in the loop, you have to return something from the method and use that in the code of the loop:
for(int i = 0; i < gridview.rows.count - 1; i++) {
//some operation;
if (aFunction(param1,param2)) {
// do something more here
}
}
public bool aFunction(param1,param2) {
//some operation;
if(abc) {
//skip the current for-loop i.e i want to do "continue" here;
return false;
} else {
//normal
return true;
}
}
public static void main(String[] args) {
int param1 = 0, param2 = 0;
getResult(param1, param2);
}
public static void getResult(Object param1, Object param2) {
for (int i = 0; i < gridview.rows.count - 1; i++) {
if (!Regex.IsMatch(RechargeText, "successfully")) {
RechargeStatus = "Failed";
Program.sp.SoundLocation = System.IO.Path
.GetDirectoryName(System.Reflection.Assembly
.GetExecutingAssembly().Location)
+ "/aimlife_error.wav";
Program.sp.Play();
} else if (Regex.IsMatch(RechargeText, "Processing")
|| Regex.IsMatch(RechargeText, "Not")) {
// just skip here then
continue;
} else {
Program.sp.SoundLocation = System.IO.Path
.GetDirectoryName(System.Reflection.Assembly
.GetExecutingAssembly().Location)
+ "/aimlife_success.wav";
Program.sp.Play();
}
Program.StatusMessage = "Recharge Successful";
TextFill();
}
}
You should extract
Program.sp.SoundLocation = System.IO.Path
.GetDirectoryName(System.Reflection.Assembly
.GetExecutingAssembly().Location)
+ "/aimlife_success.wav";
Program.sp.Play();
and
RechargeStatus = "Failed";
Program.sp.SoundLocation = System.IO.Path
.GetDirectoryName(System.Reflection.Assembly
.GetExecutingAssembly().Location)
+ "/aimlife_error.wav";
Program.sp.Play();
into its own methods to make this code clearer, looks like a mess.
The following code was a proof of concept for a message batching routine. Do I avoid goto like the plague and rewrite this code? Or do you think the goto is an expressive way to get this done?
If you'd rewrite please post some code...
var queue = new Queue<TraceItem>(this.batch);
while (this.connected)
{
byte[] buffer = null;
try
{
socket.Recv(out buffer);
}
catch
{
// ignore the exception we get when the socket is shut down from another thread
// the connected flag will be set to false and we'll break the loop
}
HaveAnotherMessage:
if (buffer != null)
{
try
{
var item = TraceItemSerializer.FromBytes(buffer);
if (item != null)
{
queue.Enqueue(item);
buffer = null;
if (queue.Count < this.batch && socket.Recv(out buffer, ZMQ.NOBLOCK))
{
goto HaveAnotherMessage;
}
}
}
catch (Exception ex)
{
this.ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
this.tracer.TraceException(TraceEventType.Error, 0, ex);
}
}
// queue processing code
}
Pretty much sums up my thoughts on "goto."
Goto is bad programming practice for many reasons. Chief among them is that there is almost never a reason for it. Someone posted a do..while loop, use that. Use a boolean to check if you should continue. Use a while loop. Goto's are for interpreted languages and a call back to assembler days (JMP anyone?). You're using a high level language for a reason. So that you and everyone else doesn't look at your code and get lost.
To keep this answer somewhat current I'd like to point out that a combination of goto and bracing errors caused a major SSL bug in iOS and OS X.
Replace the goto with a do-while, or simply a while loop if you don't want the "always run once" functionality you have right now.
var queue = new Queue<TraceItem>(this.batch);
while (this.connected)
{
byte[] buffer = null;
try
{
socket.Recv(out buffer);
}
catch
{
// ignore the exception we get when the socket is shut down from another thread
// the connected flag will be set to false and we'll break the loop
}
do {
if (buffer != null)
{
try
{
var item = TraceItemSerializer.FromBytes(buffer);
if (item != null)
{
queue.Enqueue(item);
buffer = null;
}
}
catch (Exception ex)
{
this.ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
this.tracer.TraceException(TraceEventType.Error, 0, ex);
}
}
} while(queue.Count < this.batch && socket.Recv(out buffer, ZMQ.NOBLOCK))
// queue processing code
}
It's so amazingly easy to rid yourself of GOTO in this situation it makes me cry:
var queue = new Queue<TraceItem>(this.batch);
while (this.connected)
{
byte[] buffer = null;
try
{
socket.Recv(out buffer);
}
catch
{
// ignore the exception we get when the socket is shut down from another thread
// the connected flag will be set to false and we'll break the loop
}
bool hasAnotherMessage = true
while(hasAnotherMessage)
{
hasAnotherMessage = false;
if (buffer != null)
{
try
{
var item = TraceItemSerializer.FromBytes(buffer);
if (item != null)
{
queue.Enqueue(item);
buffer = null;
if (queue.Count < this.batch && socket.Recv(out buffer, ZMQ.NOBLOCK))
{
hasAnotherMessage = true;
}
}
}
catch (Exception ex)
{
this.ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
this.tracer.TraceException(TraceEventType.Error, 0, ex);
}
}
}
// queue processing code
}
I guess the goto is SLIGHTLY more readable intuitively... But if you WANTED to avoid it I think all you'd have to do is throw the code in a while(true) loop, and then have a break statement at the end of the loop for a normal iteration. And the goto could be replaced with a continue statement.
Eventually you just learn to read and write loops and other control flow structures instead of using goto statements, at least in my experience.
Kind of related to Josh K post but I'm writing it here since comments doesn't allow code.
I can think of a good reason: While traversing some n-dimensional construct to find something. Example for n=3 //...
for (int i = 0; i < X; i++)
for (int j = 0; j < Y; j++)
for (int k = 0; k < Z; k++)
if ( array[i][j][k] == someValue )
{
//DO STUFF
goto ENDFOR; //Already found my value, let's get out
}
ENDFOR: ;
//MORE CODE HERE...
I know you can use "n" whiles and booleans to see if you should continue.. or you can create a function that maps that n-dimensional array to just one dimension and just use one while but i believe that the nested for its far more readable.
By the way I'm not saying we should all use gotos but in this specific situation i would do it the way i just mentioned.
You could refactor is to something like this.
while (queue.Count < this.batch && buffer != null)
{
try
{
var item = TraceItemSerializer.FromBytes(buffer);
buffer = null;
if (item != null)
{
queue.Enqueue(item);
socket.Recv(out buffer, ZMQ.NOBLOCK)
}
}
catch (Exception ex)
{
this.ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
this.tracer.TraceException(TraceEventType.Error, 0, ex);
}
}
Umm, I'm not really sure you want to goto out of a try block. I'm pretty sure that is not a safe thing to do, though I'm not 100% sure on that. That just doesn't look very safe...
Wrap the "HaveAnotherMessage" into a method that takes in the buffer and may call itself recursively. That would seem to be the easiest way to fix this.
I would avoid goto in this case, and refactor it. The method reads too long in my opinion.
I think your method is too big. It mixes different levels of abstraction, like error processing, message retrieval and message processing.
If you refactor it in different methods, the goto naturally goes away (note: I assume your main method is called Process):
...
private byte[] buffer;
private Queue<TraceItem> queue;
public void Process() {
queue = new Queue<TraceItem>(batch);
while (connected) {
ReceiveMessage();
TryProcessMessage();
}
}
private void ReceiveMessage() {
try {
socket.Recv(out buffer);
}
catch {
// ignore the exception we get when the socket is shut down from another thread
// the connected flag will be set to false and we'll break the processing
}
}
private void TryProcessMessage() {
try {
ProcessMessage();
}
catch (Exception ex) {
ProcessError(ex);
}
}
private void ProcessMessage() {
if (buffer == null) return;
var item = TraceItemSerializer.FromBytes(buffer);
if (item == null) return;
queue.Enqueue(item);
if (HasMoreData()) {
TryProcessMessage();
}
}
private bool HasMoreData() {
return queue.Count < batch && socket.Recv(out buffer, ZMQ.NOBLOCK);
}
private void ProcessError(Exception ex) {
ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
tracer.TraceException(TraceEventType.Error, 0, ex);
}
...