Async/Await support for Specflow Steps =>
I would like to use SpecFlow with the Async Await Features of C#, windows phone 8,
SpecFlow with MSTest can execute Code using async / await but doesn't wait for the Results.
I've changed BindingInvoker.cs and upgraded to .NET 4, in order to support async tasks, and receiving now IOC is not initialized errors.
https://github.com/robfe/SpecFlow/commit/507368327341e71b2f5e2a4a1b7757e0f4fb809d
Yes. SpecFlow does support async steps
See https://docs.specflow.org/projects/specflow/en/latest/Bindings/Asynchronous-Bindings.html
For example:
[When(#"I want to get the web page '(.*)'")]
public async Task WhenIWantToGetTheWebPage(string url)
{
await _webDriver.HttpClientGet(url);
}
It will not continue to the next step until this step was finished but it will release the thread to perform other tests
The problem here is if i put something on background thread then in test execution mode, main thread does not know about it and it just jump to the next piece of code to exectue and verify the result, but uptill that point values are not updated on the background thread. So gives wrong assert. The way to handle this problem is make the main thread to wait/sleep untill background work is over.
Example:
Dim caller As AsyncMethodHandler
Dim result As IAsyncResult
caller = New AsyncMethodHandler(AddressOf lcl_service.CreateSession)
result = caller.BeginInvoke(parameter, Nothing, AddressOf AsyncCallback, Nothing)
While Not result.IsCompleted
Thread.Sleep(1)
End While
The async support is already added to SpecFlow and will be included in the text release. You can use the CI build to check it out.
See https://github.com/techtalk/SpecFlow/issues/542
Related
When I run my xUnit unit tests I sometimes get an error message like "Transaction (Process ID 58) was deadlocked on lock resources with another process and has been chosen as the deadlock victim" on one or more of the tests, seemingly randomly. If I re-run any failing test on its own it passes.
What should I do to prevent this? Is there an option to run the tests one-after-another instead of all at once?
(N.B. I'm running the tests over the API methods in my ASP.Net 5 MVC controllers under Visual Studio 2015)
Here's an example of one of my occasionally failing tests:
[Fact]
private void TestREAD()
{
Linq2SQLTestHelpers.SQLCommands.AddCollections(TestCollections.Select(collection => Convert.Collection2DB(collection)).ToList(), TestSettings.LocalConnectionString);
foreach (var testCollection in TestCollections)
{
var testCollectionFromDB = CollectionsController.Get(testCollection.Id);
Assert.Equal(testCollection.Description, testCollectionFromDB.Description);
Assert.Equal(testCollection.Id, testCollectionFromDB.Id);
Assert.Equal(testCollection.IsPublic, testCollectionFromDB.IsPublic);
Assert.Equal(testCollection.LayoutSettings, testCollectionFromDB.LayoutSettings);
Assert.Equal(testCollection.Name, testCollectionFromDB.Name);
Assert.Equal(testCollection.UserId, testCollectionFromDB.UserId);
}
}
There are two methods the test calls, here's the controller method:
[HttpGet("{id}")]
public Collection Get(Guid id)
{
var sql = #"SELECT * FROM Collections WHERE id = #id";
using (var connection = new SqlConnection(ConnectionString))
{
var collection = connection.Query<Collection>(sql, new { id = id }).First();
return collection;
}
}
and here's the helper method:
public static void AddCollections(List<Collection> collections, string connectionString)
{
using (var db = new DataClassesDataContext(connectionString))
{
db.Collections.InsertAllOnSubmit(collections);
db.SubmitChanges();
}
}
(Note that I'm using Dapper as the micro-ORM in the controller method and so, to avoid potentially duplicating errors in the test, I'm using LINQ to SQL instead in the test to set-up and clean-up test data.)
There are also database calls in the unit test's class's constructor and Dispose method. I can add them to the post if needed.
OK, so looks like a plain vanilla case of deadlocks in your app and the need to handle that - what is your plan on the app side?
The tests and their data rigging can potentially fall prey to the same thing. xUnit doesnt have anything to address this and I'd strongly argue it shouldnt.
So in both the test and the app, you need failure/retry management.
For a web app, you have a fire them a picture of a whale and let them try again pattern but ultimately you want a real solution.
For a test, you don't want whales and definitely want to handle it, i.e. not be brittle.
I'd be using Poly to wrap retry decoration around anything in either the app or the tests that's prone to significant failures -- your exercise is to figure out what are the significant failures in your context.
Under normal circumstances a database with a single reader/writer operating synchronously shouldn't deadlock. Analysing why it happens is a matter of doing the analysis on the DB side. The tools that side would also likely quickly reveal to you if e.g. you have some aspect of your overall System Under Test which is resulting in competing work.
(Obviously your snippets are incomplete as there is a disconnect between CollectionsController.Get(testCollection.Id) and the fact that the controller method is not static - the point of this discussion should not be down at that level IMO though)
I'm trying to get the CoreDispatcher in C++ on Windows Phone 8 so that I can submit work items to the UI thread Dispatcher so I can update UI elements on the UI thread. However, when I call CoreWindow::GetCurrentForThread(), I get NULL back. In the documentation it states that this is supported on WP8. As long as I'm getting NULL for the current Window, I can't get the current Dispatcher from it; does anyone know how to get the current Dispatcher on WP8?
CoreWindow::GetForCurrentThread() is documented as returning:
The CoreWindow for the currently active thread.
If you call this function from a thread that does not have a CoreWindow (like any non-UI thread), then this function will return nullptr.
Assuming the application has finished initializing and there is a view, you can use the dispatcher from the main view of the application via CoreApplication::MainView. Alternatively, you can pass the Dispatcher^ for the UI thread to the code executing on the non-UI thread so that it has access to it when it needs to invoke back onto the UI thread.
I have used
await CoreApplication.Views.First().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
//your code here
});
I am trying to build a general exception handler for a swing application as described here: http://www.javaspecialists.eu/archive/Issue081.html
I work in jython (python syntax getting compiled to java and executed). My code looks roughly like this (updated):
def launcher(func):
class launcherThread(Runnable):
def __init__(self):
super(launcherThread, self).__init__()
def run(self):
func()
#trying to get the name which can be used to instantiate this in java
cls = ExceptionGroup().getClass()
fullName = cls.__module__ + '.' + cls.__name__
System.setProperty("sun.awt.exception.handler", fullName)
Thread(ExceptionGroup(), launcherThread(), 'Cross ExceptionHandlerThread').start()
class ExceptionGroup(ThreadGroup):
def __init__(self):
super(ExceptionGroup, self).__init__("HardenedGroup")
def uncaughtException(self, thread, exception):
#make a fancy dialog displaying str(exception)
If I test it it works fine however in the production enviornment it failes.
For testing I launch my program in Eclipse (PyDev), the production enviornment is a third party application written in Java, that has a Jython console build in. The application supports adding of custom menu entries, and putting jython scripts on these.
The main difference I see between testing and production enviornment is that in the production enviornment the swing threads are allready started (the third party application utilitizes swing). Does this cause my ThreadGroup setting to fail, or is there another reason why this is not working?
How can I get the Involved threads (exceptions ar thrown as a result of buttonActions) to check their defaultException handlers? If (as I am afraid) it should turn out that the third party installed its own handler (all exceptions are written to a log file) how can I make a new swing worker thread? (I don't want to catch the exceptions created by the host application after all)
Question recap:
1. How can I check which threads are started for the function func passed into the launcher function and see thier uncaught exception handler?
2. Can I enforce a seperate swing dispatcher for my gui part and the main applications gui part? (If I exitOnClos on a frame of my add in, the third party application closes)?
Update:
Considering the anwser from lbalazscs I am trying to use the sun.awt.exception.handler property, but it has no effect, the exceptions still end up in the log file (applications dfeault behaviour). Am I using it right? (p.s.: I am on Java 1.6)
If you have Java 5 or higher, you can also use Thread.setDefaultUncaughtExceptionHandler(), which is also described in a newer "Java Specialists' Newsletter":
http://www.javaspecialists.eu/archive/Issue089.html
And here is the newest Java 7 version:
http://www.javaspecialists.eu/archive/Issue196.html
Also see this:
Why bother with setting the "sun.awt.exception.handler" property?
EDIT: This is how I use Thread.setDefaultUncaughtExceptionHandler (in Java...):
public static void setupGlobalExceptionHandling() {
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
handleException(e);
}
});
}
I have ported my code to the RTM version of both WinRT and Rx. I use ReactiveUI in my ViewModels. Before porting the code my unit tests were running without problem but now I got a strange behavior.
Here the test:
var sut = new MyViewModel();
myViewModel.MyCommand.Execute(null) //ReactiveAsyncCommand
Assert.AreEqaul(0, sut.Collection.Count)
If I debug the test step by step, the assertion is not failing, but using the test runner it's failing...
The Collection asserted is modified by a method subscribing to the command:
MyCommand.RegisterAsyncTask(_ => DoWork())
.ObserveOn(SynchronizationContext.Current)
.Subscribe(MethodModifyingCollection);
The code was working before moving it to the RTM. I tried also to remove the ObserveOn and add an await Task.Delay() before the Assert without success.
Steven's got the rightish answer, but there are a few RxUI specific things missing. This is definitely related to scheduling in a test runner, but the reason is that the WinRT version of ReactiveUI can't detect properly whether it's in a test runner at the moment.
The dumb workaround for now is to set this at the top of all your tests:
RxApp.DeferredScheduler = Scheduler.CurrentThread;
Do not use the TestScheduler for every test, it's overkill and actually isn't compatible with certain kinds of testing. TestScheduler is good for tests where you're simulating time passing.
Your problem is that MSTest unit tests have a default SynchronizationContext. So ObserveOn and ReactiveAsyncCommand will marshal to the thread pool instead of to the WPF context. This causes a race condition.
Your first and best option is the Rx TestScheduler.
Another option is to await some completion signal (and ensure your test method is async Task, not async void).
Otherwise, if you just need a SynchronizationContext, you can use AsyncContext from my AsyncEx library to execute the tests within your own SynchronizationContext.
Finally, if you have any code that directly uses Dispatcher instead of SynchronizationContext, you can use WpfContext from the Async CTP download.
I recently encountered a problem with asynchronous operations in MSMQ. In .NET 2.0, 3.0 and 3.5, if there is a pending asynchronous receive, and the queue is deleted, the callback is invoked and upon calling EndReceive, the exception is thrown.
In .NET 4.0, the callback is never invoked, but the exception can be caught by the AppDomain.UnhandledException event handler. When running in the debugger, the application will simply terminate with no notification from Visual Studio that an exception occurred.
This code is executing on Windows 7 Professional, 64-bit. However the behavior is the same whether the application is targeting x86 or x64. (Edit: verified this behavior on XP SP3 32-bit as well - this appears to be a framework bug, not OS-related)
I am assuming this new behavior is related to .NET 4.0 being a completely new runtime. I'm not sure what to do at this point, but essentially I am looking to get the pre-.NET 4.0 behavior back, while still targeting the .NET 4.0 runtime. Any help or advice would be greatly appreciated. Here is sample code to reproduce the problem:
class Program
{
static void Main( string[] args )
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler( CurrentDomain_UnhandledException );
string path = #".\private$\mytestqueue";
// Create queue only if it doesn't already exist.
var queue = MessageQueue.Exists( path ) ? new MessageQueue( path ) : MessageQueue.Create( path );
queue.BeginReceive( TimeSpan.FromSeconds( 15 ), queue, new AsyncCallback( ReceiveComplete ) );
Thread.Sleep( 5000 );
MessageQueue.Delete( path );
}
static void CurrentDomain_UnhandledException( object sender, UnhandledExceptionEventArgs e )
{
var mqEx = (MessageQueueException) e.ExceptionObject;
// .NET 4.0:
// "The queue does not exist or you do not have sufficient
// permissions to perform the operation."
Console.WriteLine( mqEx.Message );
// "QueueNotFound"
Console.WriteLine( mqEx.MessageQueueErrorCode );
}
static void ReceiveComplete( IAsyncResult ar )
{
// This callback is never invoked under .NET 4.0.
Console.WriteLine( "Finishing Receive." );
var queue = (MessageQueue) ar.AsyncState;
try
{
queue.EndReceive( ar );
}
catch ( MessageQueueException mqEx )
{
// .NET 2.0 through 3.5:
// "Queue handle can no longer be used to receive messages
// because the queue was deleted. The handle should be closed."
Console.WriteLine( mqEx.Message );
// "QueueDeleted"
Console.WriteLine( mqEx.MessageQueueErrorCode );
}
}
}
Addendum:
After spending way too much time trying to use source stepping (System.Messaging source is available for 4.0 but not for 2.0/3.5, it appears), and hunting through the two different System.Messaging assemblies with Reflector, I finally found the problem.
In the 2.0 assembly, some try/catch blocks are used in the MessageQueue.AsynchronousRequest.RaiseCompletionEvent method to catch exceptions and store an error code so that the exception can be raised when .EndReceive() is called. However, in the 4.0 assembly, these try/catches are gone, so when an exception occurs the process must terminate since they are un-caught on a background thread.
Unfortunately this doesn't help me fix the problem. I am considering switching to a synchronous Receive, but I liked the idea of taking advantage of I/O completion ports for this.
Well, I am going to answer this and accept it, since I think it's the best answer for the near future. It could be months (or more) before there is a proper solution.
As mentioned above, I filed a bug report on Microsoft Connect, so it is pretty much up to them to revert the behavior to how it worked in CLR 2.0.
Microsoft Connect: http://connect.microsoft.com/VisualStudio/feedback/details/626177/messagequeue-beginreceive-asynchronous-exception-behavior
As far as how this affects my application, I am not willing to switch to a synchronous Receive method, as that would consume all of the available worker threads on the thread pool. My application frequently creates and removes a lot of queues, and this issue arose when a command to remove a queue was issued, but an outstanding read operation was pending. Instead, I will just mark that a queue needs to be removed, and once a safe period of time has elapsed (two times the BeginReceive timeout, for instance), I will actually remove the queue.
Or switch to a different queuing system than MSMQ, though I've been happy with it so far.