Check if element exists appium C# - c#

I have made a number of unit tests and I'm running them using appium. When an error pops up I try and capture it by
if (PowerPointSession.FindElementByAccessibilityId("CreateErrorIcon").Displayed == true)
{
exception = "An error occured when creating Agenda/TOC";
ExceptionHandler(exception);
}
This works fine if I have an error and it finds an element called CreateErrorIcon. However if no error pops up it seems to get stuck at the beginning of the if statement as if it is checking for an element called CreateErrorIconto be displayed and for some reason it never gets out of the if statement if it doesn't find the element.
Has anyone got any ideas or can point me in the right direction on why this is happening?

This post answers your question.
Basically, FindElementByAccessibilityId waits until an element is found or a timeout occurs.
In C# the check would look something like:
private static bool IsElementPresent(WindowsDriver<AppiumWebElement> driver, Action findAction)
{
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.Zero);
try
{
findAction();
return true;
}
catch (Exception)
{
return false;
}
finally
{
driver.Manage().Timeouts().ImplicitlyWait(GuiTestRunner.Timeout);
}
}
and usage:
var isError = IsElementPresent(PowerPointSession,
() => PowerPointSession.FindElementByAccessibilityId("CreateErrorIcon"));
if (isError)
{
exception = "An error occured when creating Agenda/TOC";
ExceptionHandler(exception);
}

Related

C# Recreating an exception for testing

How would I go about recreating a "The specified network name is no longer available" exception for testing.
The following code below is trying to copy a file on the same network. If the connection to the network is lost, I would like to recall the CopyFile method and try running it after a couple seconds before throwing the exception. What would be the most easiest way to test this exception?
private void CopyFile()
{
int numberOfExecution = 0;
bool copying = true;
while (copying)
{
copying = false;
try
{
File.Copy(file1, file2);
}
catch (Exception ex)
{
if (ex.Message.Contains("The specified network name is no longer available"))
{
numberOfExecution += 1;
System.Threading.Thread.Sleep(5000);
if (numberOfExecution >= 5)
{
throw ex;
}
copying = true;
}
else
{
throw ex;
}
}
finally
{
}
}
}
The idea is to create a test where File.Copy resolves to a static method you've set up for testing purposes and not to System.IO.File.Copy. In other words, you mock File.Copy.
You can tailor this method to cover all cases; succeed on first try, fail at first and succeed later on, or fail on all tries.
The fact that it doesn't really copy anything and simply returns or throws is irrelevant to the method you are testing.
My advice, use an existing tool to do this; Alexei's comment points you in the right direction.

Google Firebase Auth in Unity: How to read error codes

When using the Google Firebase Authentication plugin in Unity, how do you read error codes of faulted requests?
For example, within this code:
auth.SignInWithEmailAndPasswordAsync(email, password).ContinueWith(task => {
if(task.IsFaulted){
Debug.Log("ERROR ENCOUNTERED: " + task.Exception);
return;
}
if(task.IsCompleted){
// Success!
}
});
You can see that if an error occurs I can log the exception out, which prints the following:
ERROR ENCOUNTERED: System.AggregateException: Exception of type 'System.AggregateException' was thrown.
Firebase.FirebaseException: There is no user record corresponding to this identifier. The user may have been deleted.
That's very human-readable, but not very elegant to put into a switch statement. Is there any way for me to cast the task.Exception to be a FirebaseException so I can grab the error code? And is there a list of these error codes somewhere? I can find the documentation for the FirebaseException, but the error codes aren't there. Thanks for the help!
Edit:
So while I am still hoping for an answer, I've come to think that Google expects developers to use blanket error statements based on the context of the request. For example, when failing to sign in with an email and password (as in the above code), we should use the common statement of "Email or password is incorrect." The problem with that is that I can't let the user know the difference between them providing the incorrect details versus them entering an email which doesn't have an account associated with it at all.
Hopefully you've solved this by now but I've just come across the exact same problem and I'll share my solution:
According to MSDN, System.AggregateException is a representation of one or more errors that may occur during the task execution.
Therefore, you'll need to loop through the InnerException(s) presented by the AggregateException, and look for the suspected FirebaseException:
Retrieving the FirebaseException:
AggregateException ex = task.Exception as AggregateException;
if (ex != null) {
Firebase.FirebaseException fbEx = null;
foreach (Exception e in ex.InnerExceptions) {
fbEx = e as Firebase.FirebaseException;
if (fbEx != null)
break;
}
if (fbEx != null) {
Debug.LogError("Encountered a FirebaseException:" + fbEx.Message);
}
}
Getting the Error Code:
Wish I could help here but I haven't found anything - these aren't documented within the official API, AFIK. The only reference states: "If the error code is 0, the error is with the Task itself, and not the API. See the exception message for more detail."
I encountered the same dilemma trying to find out which error code I get from Firebase and display appropriate message for the user.
The correct way to read the Firebase Exception is with this function I created:
bool CheckError(AggregateException exception, int firebaseExceptionCode)
{
Firebase.FirebaseException fbEx = null;
foreach (Exception e in exception.Flatten().InnerExceptions)
{
fbEx = e as Firebase.FirebaseException;
if (fbEx != null)
break;
}
if (fbEx != null)
{
if (fbEx.ErrorCode == firebaseExceptionCode)
{
return true;
}
else
{
return false;
}
}
return false;
}
And you can use it like this:
auth.SignInWithEmailAndPasswordAsync("test#gmail.com", "password").ContinueWith(task => {
if (task.IsCanceled)
{
Debug.LogError("SignInWithEmailAndPasswordAsync was canceled.");
return;
}
if (task.IsFaulted)
{
if(CheckError(task.Exception, (int)Firebase.Auth.AuthError.EmailAlreadyInUse))
{
// do whatever you want in this case
Debug.LogError("Email already in use");
}
Debug.LogError("UpdateEmailAsync encountered an error: " + task.Exception);
}
}
Here is some more code samples from firebase:
https://github.com/firebase/quickstart-unity/blob/master/auth/testapp/Assets/Firebase/Sample/Auth/UIHandler.cs
I got the answer from this thread:
https://github.com/firebase/quickstart-unity/issues/96
I hope this will help someone. All the best!

VS2017 doesn't give details for an exception, just crashed with null

I'm working on a UWP project and there's something funky going on with how errors are being presented to me. I don't know if it's VS2017 or how UWP is set up.
I have a piece of code that goes online and retrieves json content, sometimes the code works and sometimes it doesn't. It works when I use Expander control from UWP Community toolkit, and fails when I want to switch to GridView. When it doesn't work, it fails on GetStringAsync method of HttpClient. The strange behavior is that the exception isn't thrown in the method where the problem occurs, the code actually redirects me back without giving an error and as soon as it gets to the property that's supposed to have a value that isn't null, I get a null exception.
This is where the problem happens:
string httpContent = "";
using (HttpClient httpClient = new HttpClient())
{
try
{
httpContent = await httpClient.GetStringAsync(uri);
}
catch (Exception e)
{
// TODO: handle errors
var x = "";
}
}
This piece of code is called from within the view model. It starts with a constructor and RefreshServerKanesWrathDataAsync is the method where json is parsed.
public CncOnlinePageViewModel()
{
cnconline = new CncOnline();
cnconline.RefreshServerKanesWrathDataAsync();
}
The second I get to GetStringAsync, the code just goes back to the constructor like nothing happened, however the method never completes, it just exits back to the constructor, and therefore fails to update observable collections with data. I then get a null exception.
I wanted to test this with VS2015, but I updated some controls that are apparently only supported withing VS2017, so I can't run the code in other versions.
I also ran into an issue with the code prior to this problem, where I tried to access files in a directory without using a token. The behavior was exactly the same, the code wasn't telling me that I didn't have access to the directory I wanted to read, it was just throwing me out of the method back into the location that made the call to read the directory. Just like with the current problem, I would then run into a null exception, which wasn't where the main problem was.
I added Template10 and UWP community toolkit to the project, if that matters.
You shouldn't call an async method from a constructor unless you're willing to provide a callback.
public CncOnlinePageViewModel()
{
cnconline = new CncOnline();
var t = cnconline.RefreshServerKanesWrathDataAsync(); // assuming returns Task<string>
t.ContinueWith(OnCompleted);
}
private void OnCompleted(Task<string> task)
{
if (task.IsFaulted)
{
// Check error
var exception = task.Exception;
}
else if (task.IsCanceled)
{
// User hit cancel?
}
else
{
// All good!
var result = task.Result;
}
}
Here's a sample where RefreshServerKanesWrathDataAsync() returns just Task (not Task<result>)
public CncOnlinePageViewModel()
{
cnconline = new CncOnline();
var t = cnconline.RefreshServerKanesWrathDataAsync(); // assuming returns Task
t.ContinueWith(OnCompleted);
}
private void OnCompleted(Task task)
{
if (task.IsFaulted)
{
// Check error
var exception = task.Exception;
}
else if (task.IsCanceled)
{
// User hit cancel?
}
else
{
// All good!
}
}
On a side note, you may also need to have Visual Studio 2017 break when any exception is thrown. In VS2017, go to Debug->Windows->Exception Settings and make sure Common Language Runtime Exceptions has a check. If it has a filled box, click the box until it turns into a checkmark.
Also..., you can tap into an event raised when any task has an unobserved exception. You can do so in the constructor of App.xaml.cs
public App()
{
TaskScheduler.UnobservedTaskException += OnUnobservedException;
}
private static void OnUnobservedException(object sender, UnobservedTaskExceptionEventArgs e)
{
// Put break point here.
var ex = e.Exception;
// This will keep your app alive, but only do it if it's safe to continue.
e.SetObserved();
}

Motorolla Device Scanning Issue

I am developing in C# for the Motorola device "MC67" and I have having issues with initialising the scanner.
The code I am using seems to be generic as I have found similar examples all over the Internet; for reference here is the code that is causing me problems:
/// <summary>
/// Initialize the reader.
/// </summary>
///
public override bool InitReader()
{
Logger.Instance.Debug("InitReader");
bool result = false;
// Logger.Instance.AddToDebuggerLog("Symbol.InitReader");
// If reader is already present then fail initialize
if (this._MyReader != null)
{
return false;
}
try
{
// Create new reader, first available reader will be used.
this._MyReader = new Symbol.Barcode.Reader();
// Create reader data
this._MyReaderData = new Symbol.Barcode.ReaderData(
Symbol.Barcode.ReaderDataTypes.Text,
Symbol.Barcode.ReaderDataLengths.MaximumLabel);
// Enable reader, with wait cursor
this._MyReader.Actions.Enable();
if ((GetDeviceType() != DeviceTypes.SymbolMC3070) && (GetDeviceType() != DeviceTypes.SymbolMC3090BT))
{
this._MyReader.Parameters.Feedback.Success.BeepTime = 0;
}
else
{
this._MyReader.Parameters.Feedback.Success.BeepTime = 50;
}
SetScannerDecoderTypeToUseWithScanSys();
result = true;
}
catch (Exception ex)
{
// Something has gone wrong Initializing barcode reader etc
// Log Exception
Logger.Instance.Exception("InitReader", ex);
// Ensure reader is Disposed
if (_MyReader != null)
{
try
{
_MyReader.Dispose();
}
catch
{
// Just incase something goes wrong
Logger.Instance.Error("Error Disposing MyReader in InitReader Exception");
}
_MyReader = null;
}
// Ensure ReaderData is Disposed
if (_MyReaderData != null)
{
try
{
_MyReaderData.Dispose();
}
catch
{
// Just incase something goes wrong
Logger.Instance.Error("Error Disposing MyReaderData in InitReader Exception");
}
_MyReaderData = null;
}
// null the EventHandler
_MyEventHandler = null;
}
return result;
}
My problem is that when the above method is called, the following line produces an exception error:
this._MyReader.Actions.Enable();
The exception is "OperationFailureException" and the error message mentions "Get all supported attributes failed : E_SCN_INVALIDIOCTRL"
Now the strange thing is that I am able to actually use the scanner on the device correctly, so I can scan barcodes and read the data even with this exception but the fact that it is happening concerns me so I am trying to prevent it.
Does anyone have any idea why I am getting the exception or any suggestions of things I can try?
This is a "handled" exception in the Symbol library. Just turn off the breakpoint for thrown exception-- Ctrl-Alt-E, in the row "Common Language Runtime Exceptions" uncheck the box under "Thrown". Unfortunately if you're trying to debug an exception that isn't working correctly, you just gotta keep pressing play every time this exception comes up.
I haven't found a way to make it stop throwing the exception though... I'd really like to be able to turn off whatever feature is failing.

Annoying SQL exception, probably due to some code done wrong

I started working on this "already started" project, and I'm having a really annoying error when trying to execute some interactions with SQL Server 2008:
The server failed to resume the
transaction. Desc.:
One of these errors I get in this specific method call:
The aspx.cs Call:
busProcesso openProcess = new busProcesso(pProcessoId);
try
{
if (openProcess.GetDocument() == null)
{
//Irrelevant code.
}
}
catch{ //... }
The Business class (relevant part):
public class busProcesso : IbusProcesso
{
public Processo vProcesso { get; set; }
RENDBDataContext db;
public busProcesso()
{
vProcesso = new Processo();
}
public busProcesso(decimal pProcessoId)
{
db = new RENDBDataContext();
try
{
vProcesso = db.Processos.SingleOrDefault(x => x.Id == pProcessoId);
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}
public string GetDocument()
{
try
{
string document = null;
foreach (Processo_has_Servico ps in ListaServicosProcesso())
{
if (ps.Servico.Document != null) //Get the error right at this line.
{
document = ps.Servico.Document;
}
}
return document ;
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}
public IQueryable<Processo_has_Servico> ListaServicosProcesso()
{
db = new RENDBDataContext();
try
{
return from ps in db.Processo_has_Servicos
join s in db.Servicos on ps.Servico_Id equals s.Id
where ps.Processo_Id == vProcesso.Id
select ps;
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}
}
As I said, the error occurs right at the line:
if (ps.Servico.Document != null) from the GetDocument() method.
Opening SQL Server Activity Monitor, I see there is a process for my database (.Net SqlClient Data Provider)
After some time/use (when I start to get the "server failed to resume the transaction" error), I go to the SQL Server Activity Monitor and there's around 5 or 6 more identical processes that weren't killed and (probably) should've been. When I manually kill them, the error stops for a while, until it starts again.
I'm not really good at working in OO and all, so I'm probably missing something, maybe some way to close one of these connections. Also, any help/tip about this structure will be welcome.
PS. The error doesn't happen everytime. Sometimes it runs just perfectly. Then it starts to give the error. Then it stops. Sometimes it happens just once.. pretty weird.
The code in ListaServicosProcesso is creating the context db. Then it is returning an IQueryable.
At this point no request has been sent to the database.
Then there is a for each in the code. At this point EF says "I need to get the data from the database". So it tries to get the data.
But the context db is now out of scope, so it crashes, on the first line that tries to use the data.
There are 2 ways to get around this:
return a list from ListaServicosProcesso, this will force the database call to execute
move the for each into ListaServicosProcesso
Edit
Pharabus is correct db is not out of scope. The problem is here:
db = new RENDBDataContext();
A new instance of the context is being created without the old one being disposed. Try Dispose of db at the end of ListaServicosProcesso. Even better place db in a using statement. But then the foreach must be moved inside the using statement.
Here's a couple of ideas to try.
1/ You can attach SQL server profiler to see the query that is being executed, which will allow you to copy and paste that query to see the data that is in the database. This might be help.
2/ You never check whether ps.Servico is null - you jump straight to ps.Servico.Document. If ps.Servico is null then you will get a null reference exception if you try to access any properties on that object.
I'm not sure of the exact cause of the error you're seeing (if you Google it, the references are all over the place...), but there are a few things you could improve in your code and I've found that just cleaning things up a bit often makes problems go away. Not always, but often.
I agree with the other answerers that it would help to keep better track of your DataContext(s). For example in you're creating it once in the constructor, then again in ListaServicosProcesso(). At that point vProcesso is on one DataContext and other entities will be on another, which gets messy.
I think you could simplify the whole thing a bit, for example you could combine GetDocument() and ListaServicosProcesso() like this:
public string GetDocument()
{
try
{
// Are you sure vProcesso is not null?
if (vProcesso == null)
return null;
// Only create the context if it wasn't already created,
if (db == null)
db = new RENDBDataContext();
return db.Processo_has_Servicos
.Where(ps => ps.Processo_Id == vProcesso.Id && ps.Servico.Document != null)
.Select(ps => ps.Servico.Document) // use an implicit join
.SingleOrDefault();
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}

Categories

Resources