How to fail test if UI element is not found? - c#

I use a method that searches an UI element:
public static bool findtopuielm(string uiitemname)
{
bool res = false;
try
{
AutomationElement desktopelem = AutomationElement.RootElement;
if (desktopelem != null)
{
Condition condition = new PropertyCondition(AutomationElement.NameProperty, uiitemname);
AutomationElement appElement = desktopelem.FindFirst(TreeScope.Descendants, condition);
if (appElement != null)
{
res = true;
}
}
return res;
}
catch (Win32Exception)
{
// To do: error handling
return false;
}
}
This method is called by another one that waits an element until it appears on desktop.
public static void waittopuielm(string appname, int retries = 1000, int retrytimeout = 1000)
{
for (int i = 1; i <= retries; i++)
{
if (findtopuielm(appname))
break;
Thread.Sleep(retrytimeout);
}
}
The thing is that when I call the last function for example:
waittopuielm("Test");
It always returns true even if the element is not found, in that case I want the test to fail.
Any suggestion would be welcomed.

It looks like your waittopuielem method returns void - did you mean to post something like this version, which returns a bool?
public static bool waittopuielm(string appname, int retries = 1000, int retrytimeout = 1000)
{
bool foundMatch = false;
for (int i = 1; i <= retries; i++)
{
if (findtopuielm(appname))
{
foundMatch = true;
break;
}
else
{
Console.WriteLine("No match found, sleeping...");
}
Thread.Sleep(retrytimeout);
}
return foundMatch;
}
Other than that, your code seems to work as expected for me.
One suggestion: In your findtopuielm method, change the TreeScope value in the desktop element search from TreeScope.Descendants to TreeScope.Children:
AutomationElement appElement = desktopelem.FindFirst(TreeScope.Children, condition);
TreeScope.Descendants is probably doing more recursive searching than you want - all children of the desktop element will be searched, as well as every child of those elements (i.e. buttons, edit controls, and so forth).
So, the chances of finding the wrong element when searching for a relatively common string are high, unless you combine your NameProperty PropertyCondition with other properties in an AndCondition to narrow your search.

Related

Check All Controls If Empty And Make Exception For Some Controls

I want to check controls if they are empty and make exception for some Controls for example i want to make exception for these Textboxes Notes_txtbox and Job_txt
. This is my function but it doesn't give me correct result . It gives Notes_txtbox,Job_txt are empty :
public bool Check_Inputs_Empty_Exception(List<Control> Exception_Control_List,
TableLayoutPanel TableLayoutPanel)
{
bool is_empy = false;
foreach (Control Control in TableLayoutPanel.Controls)
{
for (int i = 0; i < Exception_Control_List.Count; i++)
{
if (Control.Name != Exception_Control_List[i].Name &&
Control.GetType() == Exception_Control_List[i].GetType())
{
if (String.IsNullOrWhiteSpace(Control.Text))
{
MessageBox.Show(Control.Name + " is empty");
is_empy = true;
}
}
}
}
return is_empy;
}
}
And this is Function Call :
if (Check_Inputs_Empty_Exception(
new List<Control> {Notes_txtbox,Job_txt}, TableLayoutPanel) == false)
{
// My Add Function
}
This is a simple and common logic flaw. Your loops are set up with the wrong logic gates. You are simply searching for any non-match, which you will always find (for every control in the control list there is a control in the exception list that is not the same control, unless the exception list has exactly one element).
Instead, search for any single match and set a flag if found. When the flag is set you move the outer loop on to the next iteration.
public bool Check_Inputs_Empty_Exception(List<Control> Exception_Control_List, TableLayoutPanel TableLayoutPanel)
{
bool is_empy = false;
foreach (Control Control in TableLayoutPanel.Controls)
{
bool found = false;
for (int i = 0; i < Exception_Control_List.Count; i++)
{
if (Control == Exception_Control_List[i])
{
found = true;
break;
}
}
if (found) continue;
if (String.IsNullOrWhiteSpace(Control.Text))
{
MessageBox.Show(Control.Name + " is empty");
is_empy = true;
}
}
return is_empy;
}
With a little LINQ you can simplify this quite a bit too. Also, if you just want textboxes, you can filter out everything else using OfType<>().
public bool Check_Inputs_Empty_Exception(List<Control> Exception_Control_List, TableLayoutPanel TableLayoutPanel)
{
bool result = false;
var emptyTextboxes = TableLayoutPanel.Controls
.OfType<TextBox>()
.Where( c => string.IsNullOrEmpty(c.Text) )
.ToList();
foreach (var control in emptyTextboxes)
{
if (!Exception_Control_List.Any( c => c == control ))
{
MessageBox.Show(control.Name + " is empty");
result = true;
}
}
return result;
}
I suggest using Linq instead of for and query the controls
// signature: more natural have "parent, excluded":
// "scan parent without excluded"
// IEnumerable<Control> - now I can pass almost any collection, say array
public static bool Check_Inputs_Empty_Exception<T>(Control parent,
IEnumerable<T> excluded)
where T : Control {
if (null == parent)
throw new ArgumentNullException(nameof(parent));
// HashSet is more efficient (and convenient) for Contains then List
HashSet<T> exceptions = excluded == null
? new HashSet<T>()
: new HashSet<T>(excluded);
// array of Controls of type T on parent with empty Text and not within exceptions
var empty = parent
.Controls
.OfType<T>()
.Where(control => !exceptions.Contains(control))
.Where(control => string.IsNullOrEmpty(control.Text))
// .OrderBy(control => control.Name) //TODO: you may want to sort the controls
.ToArray();
foreach (T ctrl in empty)
MessageBox.Show($"{ctrl.Name} is empty");
return empty.Any();
}
// If we don't have controls to exclude
public static bool Check_Inputs_Empty_Exception<T>(Control parent)
where T : Control {
return Check_Inputs_Empty_Exception<T>(parent, new T[0]);
}
usage
if (!Check_Inputs_Empty_Exception<TextBox>(TableLayoutPanel,
new TextBox[] {Notes_txtbox, Job_txt})) {
//TODO: relevant code here
}
Edit: If you want to test, say, TextBoxs only (exclude all other Controls like Panels, Buttons) you can use generics

Resharper Search with pattern method call

I want to replace this part of code using "Search with pattern...":
public bool IsDbObjectsOK()
{
var result = 0;
result = usp_IsDbObjectsOK();
if (result == 0)
return true;
return false;
}
public bool UnlockWindow()
{
var result = 0;
result = usp_UnlockWindow();
if (result == 0)
return true;
return false;
}
Replace with:
public bool IsDbObjectsOK()
{
return usp_IsDbObjectsOK() == 0;
}
public bool UnlockWindow()
{
return usp_UnlockWindow() == 0;
}
I tried to use
var $result$ = 0;
$result$ = $usp_IsDbObjectsOK$();
if ($result$ == 0)
return true;
return false;
This doesn't work, because the method call isn't found in any of the code that needs to be replaced.
How to do this?
You need to make sure that you use the correct placeholder type when you set up the search.
Here, result should be an Identifier Placeholder and usp_IsDbObjectsOK should be an Expression Placeholder. When I do that, the replace works as you'd expect.

Combining for and if loops together

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;
}
}

How do I swap 2 elements in a list [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Swap two items in List<T>
Edit: Maybe this will work for getting the 'b' value?
for (int i = 0; i < inventory.Count; i++)
{
if (inventory[a].ItemRectangle.Intersects(inventory[i].ItemRectangle))
{
itemB = inventory[i];
}
}
Edit: Here's my progress.
Item itemA;
Item itemB;
int a = -1;
int b = -1;
if (a != -1 && b != -1)
{
itemA = inventory[a];
itemB = inventory[b];
Swap(ref itemA, ref itemB);
inventory[a] = itemA;
inventory[b] = itemB;
}
And here's is where I'm getting the 'a' value.
if (item.ItemSelected == true)
{
a = item.ItemIndex;
}
else
a = -1;
I haven't figured out how to get the 'b' value because I would have to check for an item colliding with another item that are both in the same list. If anybody know how I can do this, please tell me. It would look something like this I guess:
if (item.ItemRectangle.Intersects(//the other item.ItemRectangle)
{
b = item.ItemIndex;
}
else
b = -1;
I've made a List < Item > called inventory. So now I want to implement a swap function, like this:
foreach (Item item in inventory)
{
if (mouseRectangle.Intersects(item.ItemRectangle))
{
if (Input.EdgeDetectLeftMouseDown())
{
switch (item.ItemSelected)
{
case false:
item.ItemSelected = true;
break;
case true:
item.ItemSelected = false;
break;
}
}
}
else if (Input.EdgeDetectLeftMouseDown())
{
switch (item.ItemSelected)
{
case true:
item.ItemSelected = false;
break;
}
}
else if (item.ItemSelected == true)
{
item.ItemPosition = new Vector2(mouseRectangle.X, mouseRectangle.Y);
item.ItemRectangle = new Rectangle(mouseRectangle.X, mouseRectangle.Y, 32, 32);
}
else if (item.ItemSelected == false && //a lot of checks to determine it is not intersecting with an equip slot
{
item.ItemPosition = item.OriginItemPosition;
item.ItemRectangle = item.OriginItemRectangle;
}
else if (item.ItemRectangle.Intersects(item.ItemRectangle))
{
//SwapItem(inventory, item, item);
}
So that's the part of the code I need help with. I want any item in the list to be able to swap with any other item in the list. My SwapItem method is just a placeholder, I dont actually have a SwapItem method yet.
I want the arguments that you pass in to the method to be related to the items I want to swap. So the first item would be the item that I have selected with my mouse, and the other item should be the item that the first item is intersecting with.
To swap an element of the list you can write an extension method as.
public static class ExtensionMethods
{
public static void Swap<T>(this List<T> list, int index1, int index2)
{
T temp = list[index1];
list[index1] = list[index2];
list[index2] = temp;
}
}
Remember to put the extension method inside a static class.
then you can do:
yourList.Swap(0,1); // swap element at index 0 with element at index 1
To swap the values of two variables, the easiest method is using references. This is a classic pointer exercise in c++, but it can apply to C# as well.
// Replace int with any data type / class you need
void Swap (ref int a, ref int b)
{
int c = a;
a = b;
b = c;
}
The algorithm used is very simple, and the explanation is usually done like this: you have two glasses, one with water, and one with oil. To put the oil in the first glass, you will need to use a third glass, put the water inside, then put the oil in the first glass, and the water in the second one.
Here is what I had in mind. Look for the comments, so you can understand what's going on.:
// Unlike foreach, with for I can change the values in the list
for (int i = 0; i < inventory.Count; i++)
{
if (mouseRectangle.Intersects(inventory[i].ItemRectangle))
{
if (Input.EdgeDetectLeftMouseDown())
{
// You can replace the switch with this shorter structure
// if A is a bool value, !A will have the opposite value
inventory[i].ItemSelected = !inventory[i].ItemSelected;
}
}
else if (Input.EdgeDetectLeftMouseDown())
{
// You don't need a case-switch for a single condition. An if should suffice
if (inventory[i].ItemSelected)
inventory[i].ItemSelected = false;
}
else if (inventory[i].ItemSelected == true)
{
inventory[i].ItemPosition = new Vector2(mouseRectangle.X, mouseRectangle.Y);
inventory[i].ItemRectangle = new Rectangle(mouseRectangle.X, mouseRectangle.Y, 32, 32);
}
else if (inventory[i].ItemSelected == false && //a lot of checks to determine it is not intersecting with an equip slot
{
inventory[i].ItemPosition = inventory[i].OriginItemPosition;
inventory[i].ItemRectangle = inventory[i].OriginItemRectangle;
}
// Something definitely wrong with this line, a rectangle to instersect with itself??
else if (inventory[i].ItemRectangle.Intersects(inventory[PROBABLY_SOMETHING_ELSE].ItemRectangle))
{
Swap (ref inventory[i], ref inventory[PROBABLY_SOMETHING_ELSE])
}
}

A* Algorithm System.StackOverflowException

public List<Location2D> Path(Location2D start, Location2D goal)
{
openset = new List<NodeInfo>(); // The set of tentative nodes to be evaluated, initially containing the start node.
closedset = new List<NodeInfo>(); // The set of nodes already evaluated.
path = new List<Location2D>(); // The path result.
came_from = new Dictionary<Location2D, Location2D>();
NodeInfo Start = new NodeInfo();
Start.SetLoction(start.X, start.Y);
Start.H = GetHValue(start, goal);
openset.Add(Start);
while (openset.Count > 0) { // while openset is not empty
NodeInfo current = CheckBestNode(); //the node in openset having the lowest f_score[] value
if (current.Location.Equals(goal)) {
ReconstructPathRecursive(current.Location);
return path;
}
for (int i = 0; i < 8; i++) { // neighbor nodes.
NodeInfo neighbor = new NodeInfo();
neighbor.SetLoction((ushort)(current.Location.X + ArrayX[i]), (ushort)(current.Location.Y + ArrayY[i]));
bool tentative_is_better = false;
if (closedset.Contains(neighbor))
continue;
if (!map.Cells[neighbor.Location.X, neighbor.Location.Y].Walkable) { closedset.Add(neighbor); continue; }
Double tentative_g_score = current.G + DistanceBetween(current.Location, neighbor.Location);
if (!openset.Contains(neighbor)) {
openset.Add(neighbor);
neighbor.H = GetHValue(neighbor.Location, goal);
tentative_is_better = true;
} else if (tentative_g_score < neighbor.G) {
tentative_is_better = true;
} else {
tentative_is_better = false;
}
if (tentative_is_better) {
came_from[neighbor.Location] = current.Location;
neighbor.G = tentative_g_score;
}
}
}
return null;
}
private void ReconstructPathRecursive(Location2D current_node)
{
Location2D temp;
if (came_from.TryGetValue(current_node, out temp)) {
path.Add(temp);
ReconstructPathRecursive(temp);
} else {
path.Add(current_node);
}
}
so am Implementing A* Algorithm and when it find the Goal it goes to the ReconstructPathRecursive
and then the app crash and throw this exception An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll
and This thread is stopped with only external code frames on the call stack. External code frames are typically from framework code but can also include other optimized modules which are loaded in the target process.
idk what's wrong!
It doesn't really have to be recursive, because it's tail recursive. So you can rewrite it like this:
private void ReconstructPathIterative(Location2D current_node)
{
Location2D temp;
while (came_from.TryGetValue(current_node, out temp))
{
path.Add(temp);
current_node = temp;
}
path.Add(current_node);
}
That only helps if the path was simply too long to fit on the stack, not if it was infinite.
I fixed it by adding NodeInfo Parent {get; set; } as a filed inside the NodeInfo class, and I add new List<NodeInfo> called Nodes when tentative is better :-
if (tentative_is_better) {
neighbor.Parent = current;
nodes.Add(neighbor);
neighbor.G = tentative_g_score;
}
then when it finds the goal :-
if (current.Location.Equals(goal)){
ReconstructPath(current);
path.Reverse();
return path;
}
where ReconstructPath :-
private void ReconstructPath(NodeInfo current) {
if (current.Parent == null) return;
path.Add(current.Parent.Location);
ReconstructPath(current.Parent);
}
and it works fine now.

Categories

Resources