BeforeFeature/AfterFeature does not work using SpecFlow and Coded UI - coded-ui-tests

I am not able to define a [BeforeFeature]/[AfterFeature] hook for my feature file. The application under test is WPF standalone desktop applications.
If I use [BeforeScenario]/[AfterScenario] everything works fine, the application starts without any problem, the designed steps are performed correctly and the app is closed.
Once I use the same steps with [BeforeFeature]/[AfterFeature] tags the application starts and the test fails with:
The following error occurred when this process was started: Object reference not set to an instance of an object.
Here is an example:
[Binding]
public class Setup
{
[BeforeScenario("setup_scenario")]
public static void BeforeAppScenario()
{
UILoader.General.StartApplication();
}
[AfterScenario("setup_scenario")]
public static void AfterAppScenario()
{
UILoader.General.CloseApplication();
}
[BeforeFeature("setup_feature")]
public static void BeforeAppFeature()
{
UILoader.General.StartApplication();
}
[AfterFeature("setup_feature")]
public static void AfterAppFeature()
{
UILoader.General.CloseApplication();
}
}
StartApplication/CloseApplication were recorded and auto-generated with Coded UI Test Builder:
public void StartApplication()
{
// Launch '%ProgramFiles%\...
ApplicationUnderTest Application = ApplicationUnderTest.Launch(this.StartApplicationParams.ExePath, this.StartApplicationParams.AlternateExePath);
}
public class StartApplicationParams
{
public string ExePath = "C:\\Program Files..."
public string AlternateExePath = "%ProgramFiles%\\..."
}
Noteworthy: I'm quite new with SpecFlow.
I can't figure it out why my test fails with [BeforeFeature] and works fine with [BeforeScenario].
It would be great if somebody could help me with this issue. Thanks!

I ran into a similar problem recently. Not sure if this can still help you, but it may be of use for people who stumble upon this question.
For BeforeFeature\AfterFeature to work, the feature itself needs to be tagged, tagging just specific scenarios will not work.
Your feature files should start like this:
#setup_feature
Feature: Name Of Your Feature
#setup_scenario
Scenario: ...

Related

WordPerfect COM Automation Error

In c# .Net 4.0 I am attempting to automate WordPerfect.
To do this I add a reference in my project to the wpwin14.tlb file that lives in the WordPerfect program folder.
That has the effect of creating the COM interfaces within my project.
Next I should be able to write code that instantiates a WordPerfect.PerfectScript object that I can use to automate WordPerfect.
However, when I try to instantiate the WordPerfect.PerfectScript object c# throws the error:
"Unable to cast COM object of type 'System.__ComObject' to interface
type 'WordPerfect.PerfectScript'. This operation failed because the
QueryInterface call on the COM component for the interface with IID
'{C0E20006-0004-1000-0001-C0E1C0E1C0E1}' failed due to the following
error: The RPC server is unavailable. (Exception from HRESULT:
0x800706BA)."
The thing to zero in on in that message (I do believe) is that the RPC server is unavailable.
I have tried this with WordPerfect running in the background and without. And I have gone to my services and made sure that RPC services were all running and restarting everything.
Is it possible that I am getting blocked by a firewall? That is my only faintest guess
I just wrap it as an OLE call and clean up my COM object with FinalReleaseComObject.
Here's a simple wrapper class I've been using to open Wp docs and convert them to pdf. It cleans up nicely in our automated process:
public class WpInterop : IDisposable
{
private bool _disposed;
private PerfectScript _perfectScript;
public PerfectScript PerfectScript
{
get
{
if (_perfectScript == null)
{
Type psType = Type.GetTypeFromProgID("WordPerfect.PerfectScript");
_perfectScript = Activator.CreateInstance(psType) as PerfectScript;
}
return _perfectScript;
}
}
protected void Dispose(bool disposing)
{
if (disposing)
{
Marshal.FinalReleaseComObject(_perfectScript);
}
_disposed = true;
}
public void Dispose()
{
if (_disposed == false)
{
GC.SuppressFinalize(this);
Dispose(true);
}
}
}
Make sure your version of WordPerfect has all of the service packs and hot fixes installed. This step has fixed many random-sounding issues for me over the years. Looks like you are using X4, which is no longer supported by Corel, which means that the updates are no longer on its web site. You should be running version 14.0.0.756 (SP2 plus 2 hotfixes).
I just uninstalled WPX4 and re-installed it, without the service pack updates. Running this code gave the exact error as the OP:
using System.Runtime.InteropServices;
using WordPerfect;
namespace WP14TLB
{
class Program
{
static void Main(string[] args)
{
PerfectScript ps = new PerfectScript();
ps.WPActivate();
ps.KeyType("Hello WP World!");
Marshal.ReleaseComObject(ps);
ps = null;
}
}
}
Installing the service packs "magically" fixed the problem.
BTW, for future reference, you can also try the WPUniverse forums. There are quite a few WP experts who regularly answer difficult questions.
There is also a link to the X4 updates here:

How to setup Autofac registration

Im new to dependency injection and Ive decided to use autofac as it seems to have the best 'out of the box' support for MVC5 (others might be better but im a newbie to this)
Im creating simple use scenarios and from the wiki ive got the following code in application_start in global.asax
protected void Application_Start()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterType<ArtistController>().InstancePerHttpRequest();
builder.RegisterType<ArtistService>().As<IArtistService>().SingleInstance();
builder.RegisterType<ArtistRepository>().As<IArtistRepository>().SingleInstance();
builder.RegisterType<BandMemberRepository>().As<IBandMemberRepository>).SingleInstance();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
and in my ArtistController I have this
private IArtistService _artistService;
I then have some code the retrieves and updates data, all very simple. This works ok and Im starting to get my head around the whole concept.
My question is this, do I have to register all the concrete classes Im using manually ? My app could eventually grow and I would have many, many classes so this will be a pain to manage. I did come across this
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
which as far as Im aware should register everything for me but it didnt work. Am I doing something wrong ?
ok, thanks for the advice.
the autofac website shows an example using lambdas, so I added this in global.asax
builder.RegisterAssemblyTypes(typeof(MvcApplication).Assembly)
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces();
builder.RegisterAssemblyTypes(typeof(MvcApplication).Assembly)
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces();
but that didnt work, any idea why ?
I do most (90+%) of my registrations by tagging them with this attribute:
[AttributeUsage(AttributeTargets.Class)]
[JetBrains.Annotations.MeansImplicitUse]
public class AutoRegisterAttribute : Attribute {}
Then I use this module to register those classes:
public class AutoRegisterModule : Module
{
private readonly Assembly[] _assembliesToScan;
public AutoRegisterModule(params Assembly[] assembliesToScan)
{
_assembliesToScan = assembliesToScan;
}
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(_assembliesToScan)
.Where(t => t.GetCustomAttribute<AutoRegisterAttribute>(false) != null)
.AsSelf()
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
}
public static AutoRegisterModule ForCallingAssembly()
{
return new AutoRegisterModule(Assembly.GetCallingAssembly());
}
}
So when I'm building my container, I typically just do:
builder.RegisterModule(AutoRegisterModule.ForCallingAssembly());

NUnit Inconclusive Confusion

I have the following:-
[TestFixture]
class TaskServiceTest
{
public void Implements_ITaskService()
{
var service = CreateService();
Assert.That(service, Is.InstanceOf<ITaskService>());
}
private static ITaskService CreateService()
{
return null;
}
}
When I run that in Visual Studio / Resharper It is reported as 'Inconclusive'. The explanation of which in the NUnit Docs is
The Assert.Inconclusive method indicates that the test could not be completed with the data available. It should be used in situations where another run with different data might run to completion, with either a success or failure outcome.
I don't see that holding here, so can anyone explain what I am doing wrong?
Thanks
I just realised that it is because I missed the [Test] attribute off of the unit test.
[Test]
public void Implements_ITaskService()
{
var service = CreateService();
Assert.That(service, Is.InstanceOf<ITaskService>());
}

How to use Class Initialize so that application opens in beginning,run all the tests & closes in the end

My code:
This is initialize method
[TestInitialize()]
public void MyTest Initialize()
{}
This is test 1
[TestMethod]
public void Validate_Create_Command()
{ }
This is test 2
[TestMethod]
public void Validate_Delete_Command()
{}
Right Now test1 opens application & closes the application &
test2 also opens the application & closes.
My question is how to open application once & close application after all tests completes
First I would recommend you always open at the beginning of the test and close at the end. Your recordings should be flexible enough that you can combine them to navigate to different parts of the app. I'll answer how best to do that in a moment first your actual question.
If you want to open at the start and close at the end I use this pattern
[TestClass]
public class Tests
{
[TestMethod]
public void TestMethod1()
{
UIMap.ClickNext();
UIMap.ClickPlusButton();
UIMap.AssertStuff();
}
[TestMethod]
public void TestMethod2()
{
UIMap.ClickNext();
UIMap.ClickMinusButton();
UIMap.AssertStuff();
}
[ClassInitialize()]
public static void ClassInitialize(TestContext testcontext)
{
Utilities.Launch();
}
[ClassCleanup()]
public static void ClassCleanup()
{
Utilities.Close();
}
}
public static class Utilities
{
private static ApplicationUnderTest App;
public static Launch()
{
try
{
App = ApplicationUnderTest.Launch(pathToExe);
}
catch (Microsoft.VisualStudio.TestTools.UITest.Extension.FailedToLaunchApplicationException e) {}
}
public static Close()
{
App.Close();
App = null;
}
}
To do this on a test to test basis you simple use the normal (below)
[TestInitialize()] and [TestCleanup()]
You could copy the method calls to launch and close the application from the test methods into the initialize and cleanup methods, then delete the calls from the test methods.
The way that Coded UI managed applications between test cases changed between Visual Studio 2010 and 2012, also the way that CloseOnPlaybackCleanup worked. For more details see http://blogs.msdn.com/b/visualstudioalm/archive/2012/11/08/using-same-applicationundertest-browserwindow-across-multiple-tests.aspx
You will need to re-record test 1 and test 2 to no longer open/close the application.
In TestInitialize, record the launching of your application.
In TestCleanup, record the closing of your application.
What will happen when you run the CodedUI test is:
Step 1: TestInitialize runs which launches your application
Step 2: Test1 and Test2 run (again, you will have removed
launching/closing of your app)
Step 3: TestCleanup runs which closes your application
#region Additional test attributes
//Use TestInitialize to run code before running each test
[TestInitialize()]
public void MyTestInitialize()
{
this.UIMap.OpenMyApplication();
}
//Use TestCleanup to run code after each test has run
[TestCleanup()]
public void MyTestCleanup()
{
this.UIMap.CloseMyApplication();
}
#endregion

Spec fails when run by mspec.exe, but passes when run by TD.NET

I wrote about this topic in another question.
However, I've since refactored my code to get rid of configuration access, thus allowing the specs to pass. Or so I thought. They run fine from within Visual Studio using TestDriven.Net. However, when I run them during rake using the mspec.exe tool, they still fail with a serialization exception. So I've created a completely self-contained example that does basically nothing except setup fake security credentials on the thread. This test passes just fine in TD.Net, but blows up in mspec.exe. Does anybody have any suggestions?
Update: I've discovered a work-around. After researching the issue, it seems the cause is that the assembly containing my principal object is not in the same folder as the mspec.exe. When mspec creates a new AppDomain to run my specs, that new AppDomain has to load the assembly with the principal object in order to deserialize it. That assembly is not in the same folder as the mspec EXE, so it fails. If I copied my assembly into the same folder as mspec, it works fine.
What I still don't understand is why ReSharper and TD.Net can run the test just fine? Do they not use mspec.exe to actually run the tests?
using System;
using System.Security.Principal;
using System.Threading;
using Machine.Specifications;
namespace MSpecTest
{
[Subject(typeof(MyViewModel))]
public class When_security_credentials_are_faked
{
static MyViewModel SUT;
Establish context = SetupFakeSecurityCredentials;
Because of = () =>
SUT = new MyViewModel();
It should_be_initialized = () =>
SUT.Initialized.ShouldBeTrue();
static void SetupFakeSecurityCredentials()
{
Thread.CurrentPrincipal = CreatePrincipal(CreateIdentity());
}
static MyIdentity CreateIdentity()
{
return new MyIdentity(Environment.UserName, "None", true);
}
static MyPrincipal CreatePrincipal(MyIdentity identity)
{
return new MyPrincipal(identity);
}
}
public class MyViewModel
{
public MyViewModel()
{
Initialized = true;
}
public bool Initialized { get; set; }
}
[Serializable]
public class MyPrincipal : IPrincipal
{
private readonly MyIdentity _identity;
public MyPrincipal(MyIdentity identity)
{
_identity = identity;
}
public bool IsInRole(string role)
{
return true;
}
public IIdentity Identity
{
get { return _identity; }
}
}
[Serializable]
public class MyIdentity : IIdentity
{
private readonly string _name;
private readonly string _authenticationType;
private readonly bool _isAuthenticated;
public MyIdentity(string name, string authenticationType, bool isAuthenticated)
{
_name = name;
_isAuthenticated = isAuthenticated;
_authenticationType = authenticationType;
}
public string Name
{
get { return _name; }
}
public string AuthenticationType
{
get { return _authenticationType; }
}
public bool IsAuthenticated
{
get { return _isAuthenticated; }
}
}
}
Dan,
thank you for providing a reproduction.
First off, the console runner works differently than the TestDriven.NET and ReSharper runners. Basically, the console runner has to perform a lot more setup work in that it creates a new AppDomain (plus configuration) for every assembly that is run. This is required to load the .dll.config file for your spec assembly.
Per spec assembly, two AppDomains are created:
The first AppDomain (Console) is created
implicitly when mspec.exe is
executed,
a second AppDomain is created by mspec.exe for the assembly containing the specs (Spec).
Both AppDomains communicate with each other through .NET Remoting: For example, when a spec is executed in the Spec AppDomain, it notifies the Console AppDomain of that fact. When Console receives the notification it acts accordingly by writing the spec information to the console.
This communiciation between Spec and Console is realized transparently through .NET Remoting. One property of .NET Remoting is that some properties of the calling AppDomain (Spec) are automatically included when sending notifications to the target AppDomain (Console). Thread.CurrentPrincipal is such a property. You can read more about that here: http://sontek.vox.com/library/post/re-iprincipal-iidentity-ihttpmodule-serializable.html
The context you provide will run in the Spec AppDomain. You set Thread.CurrentPrincipal in the Because. After Because ran, a notification will be issued to the Console AppDomain. The notification will include your custom MyPrincipal that the receiving Console AppDomain tries to deserialize. It cannot do that since it doesn't know about your spec assembly (as it is not included in its private bin path).
This is why you had to put your spec assembly in the same folder as mspec.exe.
There are two possible workarounds:
Derive MyPrincipal and MyIdentity from MarshalByRefObject so that they can take part in cross-AppDomain communication through a proxy (instead of being serialized)
Set Thread.CurrentPrincipal transiently in the Because
(Text is required for formatting to work -- please ignore)
Because of = () =>
{
var previousPrincipal = Thread.CurrentPrincipal;
try
{
Thread.CurrentPrincipal = new MyPrincipal(...);
SUT = new MyViewModel();
}
finally
{
Thread.CurrentPrincipal = previousPrincipal;
}
}
ReSharper, for example, handles all the communication work for us. MSpec's ReSharper Runner can hook into the existing infrastructure (that, AFAIK, does not use .NET Remoting).

Resources