visual studio web test error handling - visual-studio

I'm using Visual Studio Ultimate 2013 and have a load test that uses a web test with a number of request and web test plugins.
In my PostRequest plugin, I'm checking the http status code of the response and am flagging an error in a WebTest.Context parameter, when a hhtp code of over 400 is returned. What I want to do is pick this up in the PostTransaction WebTest plugin and update a database table. The problem is, that the test aborts when the framework detects the error and the PostTransaction plugin isn't called.
I've added a PostWebTest plugin, that I thought would be called when the test iteration aborted, but it's never hitting this when a request fails. It does hit it if the test is successful. What am I missing?
public override void PostRequest(object sender, PostRequestEventArgs e)
{
...
statusCode = e.Response.StatusCode.GetHashCode();
If (statusCode > 400)
{
e.WebTest.Context["TransactionFailCount"] = 1;
}
}
public override void PostTransaction(object sender, PostTransactionEventArgs e)
{
int transactionFailCount = Convert.ToInt32(e.WebTest.Context["TransactionFailCount"]);
if (transactionFailCount > 0)
failCount = 1;
else
passCount = 1;
...
base.PostTransaction(sender, e);
}
public override void PostWebTest(object sender, PostWebTestEventArgs e)
{
base.PostWebTest(sender, e);
}
Thanks

A Web Performance Test (WPT) will continue to execute after an error is detected unless the Stop on error property of the test is true. It is possible that some aspects of a the handling of a request are not performed after an error, but I have not seen any such cases.
Be careful of terminology. WPTs use "transactions" as a way of grouping several requests. The context (right click) menu of a request has an "Add transaction" entry that selects a range of items in the test to be included in that transaction. Perhaps you should be using the PostRequest or PostPage plugins rather than PostTransaction.
I recommend that you do some experiments with a simple two or three request WPT plus some simple plugins that just announce that they have been called. For example
public override void PostRequest(object sender, PostRequestEventArgs e)
{
e.WebTest.AddCommentToResult("PostRequest called for url " + e.Request.Url);
}
Additionally, there is a good explanation of how and when plugins are called in pages 32 to 44 of the Visual Studio Performance Testing Quick Reference Guide from Codeplex.
The statement statusCode = e.Response.StatusCode.GetHashCode(); is strange. The value of e.Response.StatusCode is an enum, it integer value can be obtained by casting. The GetHashCode method is not intended to get the numeric value of an enum. The statement would be better as statusCode = (int)e.Response.StatusCode; or the assign and test (note that if is used for conditionals in C#, not If) might be better as
statusCode = e.Response.StatusCode;
if ( e.Response.StatusCode >= System.Net.HttpStatusCode.BadRequest ) { ... }

Related

Xamarin.iOS: MobileService.InvokeApiAsync skips

I am developing an app using Xamarin.Forms to re-use as much code as possible.
Specifically, I have a static class that manages all the POST/GET requests to my Azure Web Server.
Everything single call works fantastically except for one call - this one:
public async static Task<Models.UserParkPosition> GetUserParkPositionForCurrentUserAsync()
{
var body = new JArray { App.User.Id };
var test = await AzureMobileServiceClient.Instance.MobileService.InvokeApiAsync<JArray, Models.UserParkPosition>(ConnectionsAPI, body, HttpMethod.Get, null);
return test;
}
The method above is called when the user presses a button - specifically like this:
private async Task OnGoingToTheParkClicked(object sender, EventArgs e)
{
bool success = false;
var already = await viewModel.AlreadyHavePendingRequestAsync());
Console.WriteLine("TEST");
throw new Exception();
}
When the debugger hits the "var test" line mentioned, above.... nothing happens. The code doesn't deadlock, the UI is still responsive, but the code never returns. I never see the "TEST" word and the exception is not even thrown... what happens??
All my other APIs are called in the same way, and are working correctly.
OTHER INFO:
- Same code works on UWP and Android
- The GET request arrives at the webservice, which responds in a timely fashion (< 1 sec)
Thanks to anyone who might help or even point me in the right direction!
Found the issue - InvokeApiAsync throws an exception which is not catched anywhere from any calling thread. It somehow just disappears without causing any error nor device log, nor crash. Weird, but that's how the world goes.

Windows Moible 6.5 SDK GPS Sample Bugged

I cannot seem to find a good solution for this issue online. I have a device that is running Windows Embedded Handheld 6.5. I run the solution located at below
C:\Program Files (x86)\Windows Mobile 6.5.3 DTK\Samples\PocketPC\CS\GPS
I deploy the code to my device, not an emulator, and the code breaks with a null reference exception at
Invoke(updateDataHandler);
The solution ive seen recommends changing this to below
BeginInvoke(updateDataHandler);
But now the code breaks at Main with NullRefreceException.
Application.Run(new Form1());
Has anyone found a solution for this?
Did you alter the code? updateDataHandler is initialized in Form_Load:
private void Form1_Load(object sender, System.EventArgs e)
{
updateDataHandler = new EventHandler(UpdateData);
so that object will not be NULL. But there are other annoyances with the code, especially the Samples.Location class. You may instead use http://www.hjgode.de/wp/2010/06/11/enhanced-gps-sample-update/ as a starting point and the older one: http://www.hjgode.de/wp/2009/05/12/enhanced-gps-sampe/
The main issue with the sample is that it does not use a callback (delegate) to update the UI. If an event handler is fired from a background thread, the handler can not directly update the UI. Here is what I always use to update the UI from a handler:
delegate void SetTextCallback(string text);
public void addLog(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.txtLog.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(addLog);
this.Invoke(d, new object[] { text });
}
else
{
txtLog.Text += text + "\r\n";
}
}

How to ignore user code when breaking to point of failure in test?

I've created a significant number of methods to help me perform unit test assertions in Visual Studio 2010. I've also enabled "Double-click a Failed or Inconclusive unit test result displays the point of failure in the test" option in the Test Execution options. My issue is that with these helper methods, I'd like the point of failure to be the stack frame calling my helper method, not the exception being thrown within the helper method.
Obviously, I can do "ShowDetails" and click higher in the stack, but that will pretty much cancel out any time saved by using the helper method.
I've tried using the various [Debugger*] attributes on my method without success.
Here's some example code to illustrate my issue.
public void MyTest()
{
// ACT
var res = DoSomething();
// ASSERT
AssertDateRange(res, TimeSpan.FromDays(7));
}
public static void AssertDateRange(DateTime value, TimeSpan range)
{
var difference = DateTime.Now.Subtract(value);
if (Math.Abs(range.TotalMilliseconds) - Math.Abs(difference.TotalMilliseconds) < 0)
{
throw new AssertFailedException("DateTime was not within the expected range from now.");
}
}
I'd like for the double-click to place me on the method call within the MyTest method, while it now places me on the throw within the AssertDateRange method.

Adding profile values for auto-generated user

I'm creating a ASP.NET MVC 3.0 website, and have a couple of different database initializations based on whether the site is intended for development, testing, or production. I'm stuck on the testing initialization, as I'm trying to get a test user created. I can get the user to create just fine, however when I try to add some profile values, I get: System.Web.HttpException: Request is not available in this context. Is there a way to add Profile values in a situation where the request isn't going to be available?
Following code is what is being run:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
if (ApplicationServices.GetInitialCatalog() != "tasktracker")
{
Database.SetInitializer(new TaskTrackerDropCreateDatabaseIfModelChanges());
}
else
{
Database.SetInitializer(new TaskTrackerCreateDatabaseIfNotExists());
}
using (var db = new TaskTrackerContext())
{
db.Database.Initialize(false);
}
}
public class TaskTrackerDropCreateDatabaseIfModelChanges : DropCreateDatabaseIfModelChanges<TaskTrackerContext>
{
protected override void Seed(TaskTrackerContext context)
{
// Set up the membership, roles, and profile systems.
ApplicationServices.InstallServices(SqlFeatures.Membership | SqlFeatures.Profile | SqlFeatures.RoleManager);
// Create the default accounts and roles.
if (ApplicationServices.GetInitialCatalog() == "tasktracker_testing")
{
if (Membership.GetUser("testuser", false) == null)
{
Membership.CreateUser("testuser", "password", "testuser#test.com");
MembershipUser user = Membership.GetUser("testuser", false);
user.IsApproved = true;
var profile = ProfileBase.Create("testuser");
profile.SetPropertyValue("FirstName", "test");
profile.SetPropertyValue("LastName", "user");
profile.SetPropertyValue("TimeZone", "US Mountain Standard Time");
profile.Save();
}
}
}
}
Interesting question. Have you looked at using the new Universal Providers? Dunno if you will run into the same httpcontext issue but may be worth a look: http://www.hanselman.com/blog/IntroducingSystemWebProvidersASPNETUniversalProvidersForSessionMembershipRolesAndUserProfileOnSQLCompactAndSQLAzure.aspx
Did you try to do a call of "Initialize()" :
profile.Initialize(username, true)
after your create action to see if the context should be Initialized.
By using Reflector i saw the ProfileBase of Initialize (see below) creates this kind of context from the settings:
public void Initialize(string username, bool isAuthenticated)
{
if (username != null)
{
this._UserName = username.Trim();
}
else
{
this._UserName = username;
}
SettingsContext context = new SettingsContext();
context.Add("UserName", this._UserName);
context.Add("IsAuthenticated", isAuthenticated);
this._IsAuthenticated = isAuthenticated;
base.Initialize(context, s_Properties, ProfileManager.Providers);
}
It seems working here, the SettingsContext() seems taking account of my custom properties declared in the web.config.
Regards,
I come back again because the solution I added with the "Initialize()" function in fact not run really after an other test. So in fact I found a way which runs correctly.
The problem of "request is not available in this context" in application_start in your case could be due to the application mode "Integrated" which is new from II7 instead of the Classic mode.
To see a good explain you ca go on the Mike Volodarsky's blog IIS7 Integrated mode: Request is not available in this context exception in Application_Start .
I copy/paste an extract which could indicate the main reason:
" *This error is due to a design change in the IIS7 Integrated pipeline that makes the request context unavailable in Application_Start event. When using the Classic mode (the only mode when running on previous versions of IIS), the request context used to be available, even though the Application_Start event has always been intended as a global and request-agnostic event in the application lifetime. Despite this, because ASP.NET applications were always started by the first request to the app, it used to be possible to get to the request context through the static HttpContext.Current field.* "
To solve this you can use a workaround that moves your first-request initialization from Application_Start to BeginRequest and performs the request-specific initialization on the first request.
A good example of code is done in his blog :
void Application_BeginRequest(Object source, EventArgs e)
{
HttpApplication app = (HttpApplication)source;
HttpContext context = app.Context;
// Attempt to peform first request initialization
FirstRequestInitialization.Initialize(context);
}
class FirstRequestInitialization
{
private static bool s_InitializedAlready = false;
private static Object s_lock = new Object();
// Initialize only on the first request
public static void Initialize(HttpContext context)
{
if (s_InitializedAlready)
{
return;
}
lock (s_lock)
{
if (s_InitializedAlready)
{
return;
}
// Perform first-request initialization here
//
// You can use your create profile code here....
//---
s_InitializedAlready = true;
}
}
}

Visual Studio: How to break on handled exceptions?

I would like Visual Studio to break when a handled exception happens (i.e. I don't just want to see a "First chance" message, I want to debug the actual exception).
e.g. I want the debugger to break at the exception:
try
{
System.IO.File.Delete(someFilename);
}
catch (Exception)
{
//we really don't care at runtime if the file couldn't be deleted
}
I came across these notes for Visual Studio.NET:
1) In VS.NET go to the Debug Menu >>
"Exceptions..." >> "Common Language
Runtime Exceptions" >> "System" and
select "System.NullReferenceException"
2) In the bottom of that dialog there
is a "When the exception is thrown:"
group box, select "Break into the
debugger"
3) Run your scenario. When the
exception is thrown, the debugger will
stop and notify you with a dialog that
says something like:
"An exception of type "System.NullReferenceException" has
been thrown.
[Break] [Continue]"
Hit [Break]. This will put you on the
line of code that's causing the
problem.
But they do not apply to Visual Studio 2005 (there is no Exceptions option on the Debug menu).
Does anyone know where the find this options dialog in Visual Studio that the "When the exception is thrown" group box, with the option to "Break into the debugger"?
Update: The problem was that my Debug menu didn't have an Exceptions item. I customized the menu to manually add it.
With a solution open, go to the Debug - Windows - Exception Settings (Ctrl+Alt+E) menu option. From there you can choose to break on Thrown or User-unhandled exceptions.
EDIT: My instance is set up with the C# "profile" perhaps it isn't there for other profiles?
There is an 'exceptions' window in VS2005 ... try Ctrl+Alt+E when debugging and click on the 'Thrown' checkbox for the exception you want to stop on.
Took me a while to find the new place for expection settings, therefore a new answer.
Since Visual Studio 2015 you control which Exceptions to stop on in the Exception Settings Window (Debug->Windows->Exception Settings). The shortcut is still Ctrl-Alt-E.
The simplest way to handle custom exceptions is selecting "all exceptions not in this list".
Here is a screenshot from the english version:
Here is a screenshot from the german version:
From Visual Studio 2015 and onward, you need to go to the "Exception Settings" dialog (Ctrl+Alt+E) and check off the "Common Language Runtime Exceptions" (or a specific one you want i.e. ArgumentNullException) to make it break on handled exceptions.
Step 1
Step 2
Check Managing Exceptions with the Debugger page, it explains how to set this up.
Essentially, here are the steps (during debugging):
On the Debug menu, click Exceptions.
In the Exceptions dialog box, select Thrown for an entire category of exceptions, for example, Common Language Runtime Exceptions.
-or-
Expand the node for a category of exceptions, for example, Common Language Runtime Exceptions, and select Thrown for a specific exception within that category.
A technique I use is something like the following. Define a global variable that you can use for one or multiple try catch blocks depending on what you're trying to debug and use the following structure:
if(!GlobalTestingBool)
{
try
{
SomeErrorProneMethod();
}
catch (...)
{
// ... Error handling ...
}
}
else
{
SomeErrorProneMethod();
}
I find this gives me a bit more flexibility in terms of testing because there are still some exceptions I don't want the IDE to break on.
The online documentation seems a little unclear, so I just performed a little test. Choosing to break on Thrown from the Exceptions dialog box causes the program execution to break on any exception, handled or unhandled. If you want to break on handled exceptions only, it seems your only recourse is to go through your code and put breakpoints on all your handled exceptions. This seems a little excessive, so it might be better to add a debug statement whenever you handle an exception. Then when you see that output, you can set a breakpoint at that line in the code.
There are some other aspects to this that need to be unpacked. Generally, an app should not throw exceptions unless something exceptional happens.
Microsoft's documentation says:
For conditions that are likely to occur but might trigger an exception, consider handling them in a way that will avoid the exception.
and
A class can provide methods or properties that enable you to avoid making a call that would trigger an exception.
Exceptions degrade performance and disrupt the debugging experience because you should be able to break on all exceptions in any running code.
If you find that your debugging experience is poor because the debugger constantly breaks on pointless exceptions, you may need to detect handled exceptions in your tests. This technique allows you to fail tests when code throws unexpected exceptions.
Here are some helper functions for doing that
public class HandledExceptionGuard
{
public static void DoesntThrowException(Action test,
Func<object?, Exception, bool>? ignoreException = null)
{
var errors = new List<ExceptionInformation>();
EventHandler<FirstChanceExceptionEventArgs> handler = (s, e) =>
{
if (e.Exception is AssertFailedException) return;
if (ignoreException?.Invoke(s, e.Exception) ?? false) return;
errors.Add(new ExceptionInformation(s, e.Exception, AppDomain.CurrentDomain.FriendlyName));
};
AppDomain.CurrentDomain.FirstChanceException += handler;
test();
AppDomain.CurrentDomain.FirstChanceException -= handler;
if (errors.Count > 0)
{
throw new ExceptionAssertionException(errors);
}
}
public async static Task DoesntThrowExceptionAsync(Func<Task> test,
Func<object?, Exception, bool>? ignoreException = null)
{
var errors = new List<ExceptionInformation>();
EventHandler<FirstChanceExceptionEventArgs> handler = (s, e) =>
{
if (e.Exception is AssertFailedException) return;
if (ignoreException?.Invoke(s, e.Exception) ?? false) return;
errors.Add(new ExceptionInformation(s, e.Exception, AppDomain.CurrentDomain.FriendlyName));
};
AppDomain.CurrentDomain.FirstChanceException += handler;
await test();
AppDomain.CurrentDomain.FirstChanceException -= handler;
if (errors.Count > 0)
{
throw new ExceptionAssertionException(errors);
}
}
}
If you wrap any code in these methods as below, the test will fail when a handled exception occurs. You can ignore exceptions with the callback. This validates your code against unwanted handled exceptions.
[TestClass]
public class HandledExceptionTests
{
private static void SyncMethod()
{
try
{
throw new Exception();
}
catch (Exception)
{
}
}
private static async Task AsyncMethod()
{
try
{
await Task.Run(() => throw new Exception());
}
catch (Exception)
{
}
}
[TestMethod]
public void SynchronousTest()
{
HandledExceptionGuard.DoesntThrowException(() => SyncMethod());
}
[TestMethod]
public async Task AsyncTest()
{
await HandledExceptionGuard.DoesntThrowExceptionAsync(() => AsyncMethod());
}
}

Resources