I'm using Serenity v 1.0.7. I need to add hooks in my code to ensure that code coverage metrics are saved after tests are run. Also, I'd like to save code coverage numbers before the browser is closed or navigated away from the page that is instrumented (using JSCover).
My base test suite class which all my test classes extend has this:
#Managed(uniqueSession = true)
private static WebDriver webDriver;
What I want to do is have my own custom WebDriver class which will intercept close(), navigateX(), and catch exceptions among other calls as well. I would then call my method to persist the code coverage data then proceed with the given driver command.
However, WebDriver is an interface so I cannot extend it. I can implement it. When I do this, I get 20 methods I need to overwrite but with what? How do I bind with a Serenity-managed driver instance?
I've looked into WebDriverFacade but when I write my own CustomWebDriverFacade and do a "drop-in" like this:
#Managed(uniqueSession = true)
private static CustomWebDriverFacade webDriver;
It reports "no tests were executed" and fails.
I've looked into WebDriverEventListener but it does not allow listening for close() which is critical for me since code coverage numbers are lost when the driver is closed.
I think the core question is this -> Can Serenity #Managed work with a custom WebDriver class?
Thanks for any pointers,
Rob
Related
I've managed to build some fairly simple tests that do not utilise a Page Object Model structure. The Specflow steps will just call the driver methods (such as finding an element on the page and asserting the text is correct).
The tests use NUnit as the runner and I have managed to add parallel execution by adding [Parallelizable(ParallelScope.Fixtures)] to the assembly class for the solution. This works well, but the reports that come out of NUnit are a bit messy and I'd like more useful information on them (such as screenshots).
I have since added Extent reports to the solution, whilst this works fine for when the tests run sequentially, an error message appears when running them in parallel.
The FeatureContext.Current static accessor cannot be used in multi-
threaded execution. Try injecting the feature context to the binding
class.
The Context.Current steps are used in the creation of the Extent reports. I've been reading the documentation relating to multithreading from the Specflow site, but I'm having issues understanding the concept and figuring out how I can inject FeatureContext into the binding class. I'm trying to follow this example from the site:
[Binding]
public class StepsWithScenarioContext : Steps
{
[Given(#"I put something into the context")]
public void GivenIPutSomethingIntoTheContext()
{
this.ScenarioContext.Set("test-value", "test-key");
}
}
I've also been trying to follow other examples, but I've yet to see any documentation relating how to use ScenarioContext with something like driver.findElement(By.Id("blah")).
Any help would be appreciated, I am fairly new to test automation.
You need to have a property in your Steps class:
ScenarioContext _scenarioContext.
In Constructor you adding ScenarioContext scenarioContext as a parameter and initilizing it using:
_scenarioContext = scenarioContext
Simple example:
class Steps
ScenarioContext _scenarioContext;
public Steps (ScenarioContext scenarioContext)
{
_scenarioContext = scenarioContext;
}
Only I don't know, how it will work with inheritance.
I would like my test to fail if I mock an interface using Mockery and use a shouldReceive with a non-existing method. Looking around didn't help.
For instance :
With an interface :
interface AInterface {
public function foo();
public function bar();
}
And a test case :
function testWhatever{
Mockery::mock('AInterface')->shouldReceive('bar');
$this->assertTrue(true);
}
The test will pass.
Now, refactoring time, bar method is not needed in one place (let's say it's needed on several places) and is suppressed from the interface definition but the test will still pass. I would like it to fail.
Is it possible to do such a thing using mockery (and to be able to do the same thing with a class instead of an interface) ?
Or does a workaround exist with some other tool or a testing methodology ?
Not sur if this can be understood as is, will try to make a clearer description of the issue if needed.
To ensure that Mockery doesn't allow you to mock methods that don't exist, put the following code in your PHPUnit bootstrap file (if you want this behavior for all tests):
\Mockery::getConfiguration()->allowMockingNonExistentMethods(false);
If you just want this behavior for a specific test case, put the code in the setUp() method for that test case.
Check this section of the Mockery manual on Github for more information.
If you want to make sure that the method is called only one time, you can use once().
Suppose that the class AImplementation, implements the interface AInterface, and you wanna tested that the method is called, an example could be:
Mockery::mock('AImplementation')->shouldReceive('bar')->once();
You can also use: zeroOrMoreTimes(), twice() or times(n), checkout the repo at github. Also, I recommend you this tutorial by Jeffrey W
I'm in the middle of switching from Flex Builder 3 to Flash Builder 4, and one of the problems I have run into is that support for web services in 4 is substantially different. In both IDE's I am able to import a WSDL for my web service and it will generate the appropriate client classes for communicating with the service. The generated code in each is different.
In my Flex3 code I was able to access the endpointURI property of the mx.rpc.soap.AbstractWebService, but in the Flex4 code that is generated, the new class extends com.adobe.fiber.services.wrapper.WebServiceWrapper which does not have the endpointURI property.
My project has mulitple game servers and the player picks which server they want to play on. In the past if the player wanted server 1, I would set the endpoint URI to http://game1.server.com/service.asmx, and like wise if they wanted server 2 I would set the endpoint to http://game2.server.com/service.asmx.
What am I looking for to accomplish this in Flash Builder 4?
Short Answer:
var s:ClassThatExtendsWebServiceWrapper = new ClassThatExtendsWebServiceWrapper;
s.serviceControl.endpointURI = 'http://service.com/service.asmx';
Long Answer:
Well I finally found a solution. Adobe seems to have made this much harder than it should have been.
Web Service classes that are generated by Flash Builder 4 extend the com.adobe.fiber.services.wrapper.WebServiceWrapper. WebServiceWrapper has a property called serviceControl that can be used to control the service. The problem is that not all the members of serviceControl are accessible at the application code level. Lets assume that I have a web service called GameService. When I use the data tool to connect to the web service by providing a WSDL, Flash Builder will create two classes for me automcatically.
internal class _Super_GameService extends
com.adobe.fiber.services.wrapper.WebServiceWrapper
{ ... }
public class GameService extends _Super_GameService
{}
_Super_GameService contains all the automatically generated code to make calls to the web service. GameService contains no code itself, but unlike _Super_GameService, it is public. The idea here is that any enhancements that we need to make can be made to GameService, then later on if we need to update, _Super_GameService can be regenerated, but out changes to GameService will not be overwritten by the code generation tool.
Now this leads us to usage of these generated classes. Typically all I should have to do is create an instance of GameService and call a method on it. In this example DoSomethingAwesome is a method available on the web service.
var gs:GameService = new GameService();
var token:AsyncToken = gs.DoSomethingAwesome();
Now this will call the service using the URI of the service specified in the WSDL file. In my situation I wanted GameService to connect to a different URI. This should have been simple, but things fell apart.
My first problem was that viewing the documentation on WebServiceWrapper (http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/com/adobe/fiber/services/wrapper/WebServiceWrapper.html) did not render properly in Firefox. So when I was reading the documentation I wasn't getting the full picture. This really needs to be fixed by Adobe.
Viewing the documentation in another browser helped me find out about the serviceControl property of WebServiceWrapper. serviceControl is declared as a mx.rpc.soap.AbstractWebService. AbstractWebService does have an endpointURI property which makes the following code valid.
var gs:GameService = new GameService();
gs.serviceControl.endpointURI = 'http://game1.service.com/GameService.asmx';
The other problem I had is that for some reason the endpointURI property of serviceControl does not appear in the Intellisense context menu. So since I didn't see serviceControl in the online documentation at first, and I didn't see endpointURI in intellisense, I didn't realize the property was there to be set.
If you look at the source for AbstractWebserivce, (http://opensource.adobe.com/svn/opensource/flex/sdk/trunk/frameworks/projects/rpc/src/mx/rpc/soap/AbstractWebService.as) there doesn't seem to be an Exclude tag to explain why endpointURI does not appear in the Intellisense context menu. So I don't know what is going on there.
You should be able to override the endpointURI on the WebService. But I'm not sure where to do that with the generated code since I use <s:WebService/>.
This is the only way I could get it to work, in the generated stub for your service:
import com.adobe.fiber.core.model_internal;
Also:
/**
* Override super.init() to provide any initialization customization if needed.
*/
protected override function preInitializeService():void
{
_needWSDLLoad = false; // to prevent loading the default WSDL
super.preInitializeService();
// Initialization customization goes here
wsdl = "http://localhost/yourservice?wsdl";
_needWSDLLoad = true;
model_internal::loadWSDLIfNecessary();
I am writing a small flex application that will, eventually, call PHP services to perform its work. In the meantime, however, I would like to have it use local data in XML form to allow me to develop the Flex part independently of the data service.
What is the best way to do this?
I want to emulate a service like this:
public class Service {
public function getIssues(project:String):ArrayCollection {}
public function addIssue(issue:Issue):void {}
// ...
}
Suppose I have the data stored in assets/:
assets/_project1_.data.xml
assets/_project2_.data.xml
assets/_project3_.data.xml
If I only ever needed to load one, I'd do the following:
<mx:HTTPService id="issueService"
url="assets/issues.xml"
fault="serviceFaultHandler(event)"
result="issueResultHandler(event)"/>
And invoke the service using issuerService.send(), populating my results as expected. How do I do this as though it were a RemoteObject instead, but keep my data local?
You might wrap the HTTP service in a PsuedoRemoteObject class that conforms to your service interface and returns the expected objects.
Easiest way would just be running a server locally.
I am trying to create my own EasyBinderDropDown that currently looks like this:
public class EasyBinderDropDown : DropDownList, ICanBindToObjectsKeyValuePair {
public void BindToProperties<TYPE_TO_BIND_TO>(IEnumerable<TYPE_TO_BIND_TO>
bindableEnumerable,
Expression<Func<TYPE_TO_BIND_TO, object>> textProperty,
Expression<Func<TYPE_TO_BIND_TO, object>> valueProperty) {...}
public bool ShowSelectionPrompt { get; set; }
public string SelectionPromptText { get; set; }
public string SelectionPromptValue { get; set; }
//...
}
Basically it is very helpful for easy binding to objects from inside code since you just do something like _dropDown.BindToProperties(myCustomers, c=>c.Name, c=>c.Id) and it works for you, also by setting ShowSelectionPrompt and SelectionPromptText I can easily have a "Select Customer" Line. I don't want to ask so much about my specific implementation, rather I am confused how to write unit tests for some scenarios.
For example my current tests cover the control being created properly during load and having its output render properly but I am lost as to how to test what happens when the control gets posted back. Can anyone give me some advice on how to test that? I would prefer to do this without having to mock an HTTPContext or anything like that, Is there a way I can simulate the control being rebuilt?
"I would prefer to do this without having to mock an HTTPContext or anything like that, Is there a way I can simulate the control being rebuilt."
By definition, you are not asking to "unit test"; you are looking for an "integration test". If you are not mocking the major dependencies, in this case, the ASP.NET runtime components, the what you are testing is the integration between your control and ASP.NET.
If you do not want to mock out the HttpContext and friends, then I would suggest an automated web testing framework such as Selenium or NUnitAsp.
Update: Based on the comment. Don't have the code access directly the IsPostback or other asp.net stuff. Wrap them with simple classes/interfaces. Once you have done that, send mocks that implement those interfaces. This way you don't have to mock the whole HttpContext, just the pieces that matter for the code (which are really clear based on the interfaces involved).
Also, given it is an asp.net custom control, you don't want to force requirements on external things like dependency injection. Have a default (no parameters) constructor, that sets up the control to use the asp.net stuff. Use a constructor with more parameters to send the mocked versions.
Initial answer:
It seems to me you are looking for a happy middle between unit tests and integration tests. You are working with a custom control, which can go wrong on different parts of the asp.net's page lifecycle.
I would:
Check if you can move parts of the code
out of the custom control to separate
classes, you can more easily unit test
For simple scenarios, rely on the functional tests of the rest of the project to catch any further issue with the control (use watin / selenium rc).
For more complex scenarios, as if the control will be used in different parallel projects or will be delivered to the public, set up some test pages and automate against it (again watin / selenium rc).
You write the tests in watin / selenium rc in c#, and run them in your "unit" test framework. Make sure to keep them separated from the unit tests, since they will clearly run slower.
Ps. I haven't used ms test support for asp.net, it might have some support for what you are looking for.