Getting the exception message or complete exception in MSTest using reflection - c#

I have few selenium tests and there are exception handling mechanisms for the most expected exceptions like ElementNotFoundException, ElementNotVisibleException in my global exception handling block. In the below block using the WebDriverWait I was able to handle the known exceptions but sometimes in my webpage there are chances of getting ElementNotInteractble exception and some other unhandled exceptions.
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds ((Constants.MediumWaitTime)));
wait.IgnoreExceptionTypes(
typeof(WebDriverTimeoutException),
typeof(NoSuchElementException),
typeof(ElementNotVisibleException),
typeof(StaleElementReferenceException),
typeof(ElementClickInterceptedException),
typeof(ElementNotSelectableException),
typeof(ElementNotInteractableException));
try
{
Func(TestCaseInput, testCaseStep);
}
catch (WebDriverTimeoutException webDriverTimeoutException)
{
testCaseStep.ErrorMessage = $#"""Exception Occoured in Method:
'{MethodBase.GetCurrentMethod().Name}' with Exception: '{webDriverTimeoutException.StackTrace}'
""WebDriverTimeoutException.InnerException is::"" {webDriverTimeoutException.InnerException}
""Exception occured due to timeout""";
}
Is there any way to capture or listen to unhandled exceptions in MSTest in TestCleanUp. Is there any way to get the exceptions thrown from TestExplorer using some reflection or other mechanisms in c#
NOTE: I do not want to have some try/catch blocks for every method.
I was able to handle every exception raised from selenium using the EventFiringWebDriver. This solves one part of my problem. But there are some exceptions raised from .net framework for example I'm expecting a dropdown to contain some values and select one of the value from dropdown Like
IList accounts = driver.findElements(By.XPath("//a[id='accounts']"));
accounts.FirstOrDefault().Click(). If the accounts list doesn't have any webelements then it throws a "System.InvalidOperationException: Sequence contains no matching element" . I can put an if condition before clicking the element. if(accounts.Any()) but I cannot put such conditions around all such dropdowns.
I went through some links which are helpful in the cases of asp.net or .netcore to log firstexceptions or any exceptions but I couldn't find related links to MSTest unhandled exceptions. This link https://stackify.com/csharp-catch-all-exceptions/ has been useful for asp.net or .netcore
to log every exception:

Try something like the folllowing. Extend the TestMethod and decorate with the new one.
public class SeleniumTestMethodAttribute : TestMethodAttribute
{
public override TestResult[] Execute(ITestMethod testMethod)
{
try {
base.Execute(testMethod);
}
catch (WebDriverTimeoutException webDriverTimeoutException)
{
testCaseStep.ErrorMessage = $#"""Exception Occoured in Method:
'{MethodBase.GetCurrentMethod().Name}' with Exception: '{webDriverTimeoutException.StackTrace}'
""WebDriverTimeoutException.InnerException is::"" {webDriverTimeoutException.InnerException}
""Exception occured due to timeout""";
}
}
}
And then decorate with
[SeleniumTestMethodAttribute]
public void TestMethodWithSelenium() {
}

Related

Override Exception class and Handle error without class referencing

I want to handle all errors at one place without referencing that class.
see my current structure.
public ActionResult Login(string returnUrl)
{
try
{
var a = 10;
var b = 0;
var c = a / b;
}
catch (Exception ex)
{
throw new LogEroor("", ex);
}
ViewBag.ReturnUrl = returnUrl;
return View();
}
and my error handling class.
public class LogEroor : Exception
{
public LogEroor(string message, Exception Ex) : base(message, Ex)
{
// error handling
}
}
My question
Is there any way that I can call LogError method with Ex parameter when error occurs, but I do not want to call this method in each and every catch, like I did over here.
This is a typical XY problem. The actual problem X you're trying to solve is, paraphrased:
I want to log all exceptions that occur in my web application.
Your solution Y is, paraphrased:
I will inherit from Exception, in which I will do the logging, and want any exception that is thrown to be converted to my exception type so it can be logged, without writing a try-catch block in all places where exceptions can occur.
Now you want help with problem Y, but that's the wrong approach altogether. You could do it using the AppDomain.UnhandledException event, but you shouldn't.
Your solution is in How do I log ALL exceptions globally for a C# MVC4 WebAPI app?: use exception filters.
How do you expect to call a method or even a constructor without specifiying it? What you want makes no sense at all, of course all your classes have to reference the generic exception-class if they´re up to throw one.
You could register to the AppDomain.UnhandledExceptionHandler however which is a generic handler for all not handled exceptions. So instead of catching all your exceptions and throwing them again by whrapping them you can use this:
AppDomain.UnhandledExceptionHandler += (sender, args) => { throw new LogError(args.ExceptionObject); };
But this way you would throw an exception within the last layer of exception-handling your app has. This means you throw an exception which is never caught and will make your app crash. To avoid this implement your logging directly within that event.

MS UnitTestFramework retrieve and log exceptions c#

I just started on a rather extensive automation project that uses MS's UnitTestFramework. One thing I noticed is that when there's an error in my code - not the app I test - the framework catches that error and fails the test in a nice happy way that allows for the test iteration to complete. However, I want to be able to see those exceptions & stack trace in my log4net logs, and so far I have found no way to grab them in my test cleanup (or anywhere outside of a try catch block which I have no intention of splattering in every method).
Anyone know how to get these exceptions into my logs?
You could use First-Chance Exception Notifications
via the AppDomain.FirstChanceException Event -
This event is only a notification. Handling this event does not handle
the exception or affect subsequent exception handling in any way.
After the event has been raised and event handlers have been invoked,
the common language runtime (CLR) begins to search for a handler for
the exception. FirstChanceException provides the application domain
with a first chance to examine any managed exception.
So something like this (note it is in a method marked as AssemblyInitialize, which means it runs once per test run, and the code is excluding the AssertFailedException thrown by MSTest when a test fails. You might want to exclude other exceptions as well, as otherwise there could be a lot of 'noise' in the logs.)
[TestClass]
public class Initialize
{
[AssemblyInitialize]
public static void InitializeLogging(TestContext testContext)
{
AppDomain.CurrentDomain.FirstChanceException += (source, e) =>
{
if (e.Exception is AssertFailedException == false)
LogManager.GetLogger("TestExceptions").Error(e.Exception);
};
}
}
If it feasible for you to replace the [TestMethod] attribute then you can define your own attribute MyTestMethod, say, by deriving from the default one like this:
public class MyTestMethodAttribute : TestMethodAttribute
{
public override TestResult[] Execute(ITestMethod testMethod)
{
TestResult[] testResults = base.Execute(testMethod);
foreach (var testResult in testResults.Where(e => e.Outcome == UnitTestOutcome.Failed))
testResult.LogOutput += $"Exception `{testResult.TestFailureException.GetType().Name}` with message `{testResult.TestFailureException.Message}`.";
return testResults;
}
}
The following test then produces the expected log message Exception TestFailedException with message Assert.Fail failed. Some exception text. in the standard output panel of Visual Studio's Test Explorer.
[TestClass]
public class Tests
{
[MyTestMethod]
public void Test()
=> Assert.Fail("Some exception text");
}
The approach also works when tests execute in parallel.

Error Level in Exception

I am handling errors using IErrorHandler in WCF REST. I need to log class name, method name, line number, error code etc. and i find out the soultions to all this.
But I am thinking any possibility or options to get 1ErrorLevel1 like windows event viewer. Eg: Warning, Information, Error.
Actually if I do like this my applciation exceptions can be put as Information. This can be work simple create an custom Exception class.
But my question is for other exceptions (other than my application exceptions) any option to get this level based on the error. I don't need to set this level for other types of erros.
Actually i am logging the exception in HandleError event. Now i am just throw my exceptions as applicationexception.
Just see my Service method code below:
if(!long.TryParse("534543534", out value))
{
throw new ApplicationException("Input is Not Valid!!!");
}
So in my error handling i got this as application exception. Here i dont knwo this is because of FormatException, Overflow Exception, ArgumentNullException. How i handle this. I can add the original exception as innerexception but need to wrap try..catch in each service method to get the exception. Is this good practice when i have the IErrorHandler methods. Please suggest good approach for this
In .NET, an exception is a severe error that interrupts the process of your application. The framework does (for the most part) not provide an error level as all exceptions are basically errors. If an exception is thrown, this always means that there is an error that the application cannot continue with.
If you want to discern between the exception types and write some as informational messages or warnings to your log, you'd have to inspect the exceptions in your error handler, e.g. by code similar to this:
public class MyErrorHandler : IErrorHandler
{
// ...
private static readonly Dictionary<Type, TraceLevel> _exceptionTraceLevelMappings;
static MyErrorHandler()
{
_exceptionTraceLevelMappings = new Dictionary<Type, TraceLevel>();
_exceptionTraceLevelMappings.Add(typeof(ApplicationException), TraceLevel.Information);
_exceptionTraceLevelMappings.Add(typeof(ArgumentException), TraceLevel.Warning);
}
private static TraceLevel GetLevelByExceptionType(Type exType)
{
// You might want to add a more sophisticated approach here (e.g. for base classes)
if (_exceptionTraceLevelMappings.ContainsKey(exType))
return _exceptionTraceLevelMappings[exType];
return TraceLevel.Error;
}
// ...
}
Based upon the comments, you want to discern between errors that are raised to coding mistakes and input data validation errors. In this case, you'd need to implement a CustomException type and use TryParse to validate input data:
public class MyValidationException : Exception
{
public MyValidationException(string message)
: base(message)
{
}
// A custom exceptions needs several constructors, so add them also
}
In your service code, you'd use TryParse as in your sample:
if(!long.TryParse("534543534", out value))
{
throw new MyValidationException("Input is Not Valid!!!");
}
In the mapping dictionary, you can register your exception type and assign TraceLevel.Information:
// ...
_exceptionTraceLevelMappings.Add(typeof(MyValidationException), TraceLevel.Information);
// ...

I want to assert that an exception was thrown within a certain class

I am building a TestProject for my client/server setup. I want to verify that a test fails within a certain block of execution (there is no client to send to so the server's Send() method will throw an exception). Since I do not want to have the tests boot up a client and server and have them communicate (which I have had problems doing on a single machine.)
If the code reaches this line, that means that the program's execution flow could only fail within the responsibilities of another test. Is there an easier way to do this other than doing a substring check on the thrown exception's stacktrace? I feel like this method is not very expandable and would require constant attention if class names change.
Is there a way that doesn't even involve manually checking the exception's stacktrace?
If you are using NUnit
Without using DataAnnotations
[Test]
public void Test_XXXXXXX
{
var yourClass = new YourClass();
Assert.That(()=>yourClass.Method(),
.Throws.Exception
.TypeOf<TypeOfYourException>
.With.Property("Message")
.EqualTo("the message you are expecting goes here")
);
}
Using DataAnnotations
[Test]
[ExpectedException(typeof(ExceptionType), ExpectedMessage="your message goes here!")]
public void Test_XXXXXXX
{
var yourClass = new YourClass();
// Call your method in a way that it will fail
yourClass.YourMethod();
}
Is there anything unique about the exception in the class, other than that it's specific to that class?
If it's identifiable by the message you can test it as the other answer has shown, or like this if you're not using NUnit:
try {
myMethod();
Assert.Fail("Expected exception to be thrown.");
} catch (MyException ex) {
Assert.Equals("My Exception Message", ex.Message, "Exception message was formatted incorrectly.");
} catch (Exception) {
Assert.Fail("An exception was thrown, but of the wrong type.");
}
When you are unit-testing some class, there is two sources of exception:
Class which you are testing can throw an exception
Dependency of a class can throw an exception
In second case you usually either handle exception, or wrap it in more high-level exception and throw it to caller. So, how to test all these cases?
System under test throws exception
E.g. throwing exception in case of wrong argument passed to method (NUnit sample):
StockService service = new StockService();
Assert.Throws<ArgumentNullException>(() => service.Connect(null));
You don't need to check stack trace, because it's a class under test who supposed to throw exception.
Dependency throws exception and we handle it
When your class has dependencies, you should mock dependencies in order to test your class in isolation. So, it's very easy to setup mocks to throw exceptions when your class interacts with them. Consider case when service should run on default settings if configuration file not found (Moq sample):
var configMock = new Mock<IStockServiceConfig>();
configMock.Setup(c => c.Load()).Throws<FileNotFoundException>();
StockService service = new StockService(configMock.Object);
service.Connect("google");
configMock.VerifyAll();
Assert.That(service.Port, Is.EqualTo(80));
This test will fail if you will not try to load config, or if you will not handle FileNotFoundException.
Exception stacktrace does not matters here - we don't care whether our direct dependency thrown exception, or it was some other class inside dependency. Actually we don't know if that class exists - we are interacting only with direct dependency. And we should care only about fact that dependency can throw exception, which we can handle.
Dependency throws exception and we wrap it
And last case - wrapping exception in something more high-level. Consider previous sample, but config is really important and you can't start without configuration file. In this case you wrap FileNotFoundException into something more business-specific, which makes sense at higher levels of your application. E.g. StockServiceInitializationException:
var configMock = new Mock<IStockServiceConfig>();
configMock.Setup(c => c.Load()).Throws<FileNotFoundException>();
StockService service = new StockService(configMock.Object);
Assert.Throws<StockServiceInitializationException>(_ => service.Connect("bing"));
configMock.VerifyAll();
As you can see, we also don't care about stacktrace of exception, which throws our dependency. It also could be some wrapper of more low level exception. Expected behavior of service - throw high-level initialization exception if config not found. We are verifying that behavior here.

Throwing multiple exceptions in .Net/C#

In an application I work on, any business logic error causes an exception to be thrown, and the calling code handles the exception. This pattern is used throughout the application and works well.
I have a situation where I will be attempting to execute a number of business tasks from inside the business layer. The requirement for this is that a failure of one task should not cause the process to terminate. Other tasks should still be able to execute. In other words, this is not an atomic operation. The problem I have is that at the end of the operation, I wish to notify the calling code that an exception or exceptions did occur by throwing an exception. Consider the following psuedo-code snippet:
function DoTasks(MyTask[] taskList)
{
foreach(MyTask task in taskList)
{
try
{
DoTask(task);
}
catch(Exception ex)
{
log.add(ex);
}
}
//I want to throw something here if any exception occurred
}
What do I throw? I have encountered this pattern before in my career. In the past I have kept a list of all exceptions, then thrown an exception that contains all the caught exceptions. This doesn't seem like the most elegant approach. Its important to preserve as many details as possible from each exception to present to the calling code.
Thoughts?
Edit: The solution must be written in .Net 3.5. I cannot use any beta libraries, or the AggregateException in .Net 4.0 as mentioned by Bradley Grainger (below) would be a nice solution for collection exceptions to throw.
The Task Parallel Library extensions for .NET (which will become part of .NET 4.0) follow the pattern suggested in other answers: collecting all exceptions that have been thrown into an AggregateException class.
By always throwing the same type (whether there is one exception from the child work, or many), the calling code that handles the exception is easier to write.
In the .NET 4.0 CTP, AggregateException has a public constructor (that takes IEnumerable<Exception>); it may be a good choice for your application.
If you're targeting .NET 3.5, consider cloning the parts of the System.Threading.AggregateException class that you need in your own code, e.g., some of the constructors and the InnerExceptions property. (You can place your clone in the System.Threading namespace inside your assembly, which could cause confusion if you exposed it publicly, but will make upgrading to 4.0 easier later on.) When .NET 4.0 is released, you should be able to “upgrade” to the Framework type by deleting the source file containing your clone from your project, changing the project to target the new framework version, and rebuilding. Of course, if you do this, you need to carefully track changes to this class as Microsoft releases new CTPs, so that your code doesn't become incompatible. (For example, this seems like a useful general-purpose class, and they could move it from System.Threading to System.) In the worst case, you can just rename the type and move it back into your own namespace (this is very easy with most refactoring tools).
Two ways of the top of my head would be either make a custom exception and add the exceptions to this class and throw that the end :
public class TaskExceptionList : Exception
{
public List<Exception> TaskExceptions { get; set; }
public TaskExceptionList()
{
TaskExceptions = new List<Exception>();
}
}
public void DoTasks(MyTask[] taskList)
{
TaskExceptionList log = new TaskExceptionList();
foreach (MyTask task in taskList)
{
try
{
DoTask(task);
}
catch (Exception ex)
{
log.TaskExceptions.Add(ex);
}
}
if (log.TaskExceptions.Count > 0)
{
throw log;
}
}
or return true or false if the tasks failed and have a 'out List' variable.
public bool TryDoTasks(MyTask[] taskList, out List<Exception> exceptions)
{
exceptions = new List<Exception>();
foreach (MyTask task in taskList)
{
try
{
DoTask(task);
}
catch (Exception ex)
{
exceptions.Add(ex);
}
}
if (exceptions.Count > 0)
{
return false;
}
else
{
exceptions = null;
return true;
}
}
You could create a custom Exception that itself has a collection of Exceptions. Then, in your Catch block, just add it to that collection. At the end of your process, check if the Exception count is > 0, then throw your custom Exception.
You might want to use a BackgroundWorker to do this for you. It automatically captures and presents any exceptions when completed, which you could then throw or log or do whatever with. Also, you get the benefit of multithreading.
The BackgroundWorker is a nice wrapper around delegate's asynchronous programming model.
No super-elegant solution here but a few ideas:
Pass an error-handler function as argument to DoTasks so the user can decide whether to continue
Use tracing to log errors as they occur
Concatenate the messages from the other exceptions in the exception bundle's message

Categories