Showing posts with label selenium toolkit. Show all posts
Showing posts with label selenium toolkit. Show all posts

Wednesday, January 05, 2011

Selenium Toolkit for .NET 0.84 Released

Welcome 2011, things are shaping up to be a great year.  Things have been quiet around here, aside from the limited notices I sent out on twitter, you may not have noticed that I published two releases of the Selenium Toolkit for .NET since November.

So what's new in the Toolkit?

While there have been a few minor fixes and code changes, the last two releases for the toolkit have been focused on keeping the toolkit current with its external dependencies (NUnit / Selenium / Selenium IDE).  As such, expect to see more frequent releases this year.

By far, the biggest change in the toolkit is the new WiX based installer.  While I’m personally excited about the ability to include the installer as part of an automated build, you can do a lot of great things with WiX’s declarative syntax that would normally require custom code.  For example, the installer is able to conditionally deploy files based on the presence of a registry key and folder value.

The second biggest change (enabled through the WiX installer) is a resolution to a common problem related to the Toolkit’s NUnit addin.  Without going into the specific details, the short story is that NUnit Addins only work with the version of NUnit it was compiled with.  This leads to some confusion where users would copy the addin to their recently installed latest version of NUnit only to find out the hard way that nothing works.  Since version 0.83 the installer now includes separate NUnit version specific addins and will deploy them to the appropriate NUnit addin folder during installation.  NUnit versions 2.5.3, 2.5.5, 2.5.7, 2.5.8 and 2.5.9 are now supported as separate addins.

In case you’re wondering, 2.5.4 and 2.5.6 were published for only a few weeks before they were superseded by 2.5.5 and 2.5.7 respectively.

Also, you asked, I listened: the Toolkit is now published as both an MSI and ZIP.

What about Selenium 2.0 / WebDriver?

As my current project at work is a monster WPF application, I haven’t had a lot of cycles to play with the new WebDriver feature-set.  This may change, as I’m planning on reaching out to some web-based projects within my organization and offer some test guidance.

As far as Selenium 2.0 betas are concerned, I am keeping a close eye on the project and as soon as the .NET bindings and overall functionality stabilize I may upgrade the internal bits to leverage the 1.0 backward compatible features in the 2.0 beta (WebDriverBackedSeleniumBrowser).  I may even fork the code and offer two releases.  Time will tell, as will your feedback.

So with that, short-n-sweet – Happy New Year.  You can find the latest release here:  http://seleniumtoolkit.codeplex.com/releases/view/58383

submit to reddit

Wednesday, August 18, 2010

An update

“The rumors of my death have been largely exaggerated." – Mark Twain.

It’s been forever and a day since my last post, largely due to the size and complexity of my current project, but for those wondering (and to clear the writers block in my head), here’s a quick update:

Selenium Toolkit for .NET

Although there hasn’t been a formal release on my open source project since last November, I have been covertly making minor commits here and there to keep the NUnit dependencies in sync with NUnit’s recent updates.  I may update the NUnit libraries to the latest release (2.5.7) this weekend.  I realize the irony here: the purpose of my project is to provide a simple installer for Selenium and my NUnit addin, forcing you to download the source and compile it is beyond excuse.  Here are some of the things that I have been tinkering with to include in a major release, but I haven’t fully sat down to finish:

  • WiX-based Installation:  I’ve been meaning to drop the out of the box Visual Studio installer project in favor of a WiX-based installer.  The real intent is to install side-by-side versions of my NUnit addin for each version of NUnit installed locally.
  • Resharper 5.0 integration:  The good folks at JetBrains, through their commitment to open source projects, have recognized my open source project and have donated a license of Resharper (read: YOU GUYS ROCK!).  To return the favor, I am looking to produce a custom runner for tests with my WebFixture attribute so that you can right click any fixture or test to launch the selenium process just like you would with NUnit or MSTest.
  • Visual Studio 2008/2010 integration: Not to leave the rest of the development world without Resharper licenses in the cold, I have been playing with a custom version MSTest extension.  Unfortunately for me, the out-of-the-box functionality for MSTest isn’t enough for my needs – I would really like to control execution of the environment before and after the test as well as when all tests have finished execution – there doesn’t seem to be a good hook for this.  It appears that my best option is to implement my own test adapter and plumbing.  I’ll leave the details of my suffering and choking on this to your imagination or maybe another post.

What about Selenium 2.0, aka WebDriver?  I’m still sitting on the fence on how to adapt the toolkit to the new API but haven’t had a lot of time to play with it since my current project is a very thick client (no web).  I am interested to hear your thoughts, but my immediate reaction is to use a parameterized approach:

[WebTest]
public void UsingDefaultBrowser(WebDriver browser)
{
}

Other Ramblings

I won’t bore you to death with the details of the last few months – my twitter stream can do that – but expect to hear me spout more on WPF / Prism / Unity, TDD, Context/Specification soon.

In the meantime, happy coding.

Monday, November 23, 2009

User Extensions with the Selenium Toolkit for .NET

As I mentioned in my last post, new to version 0.81 the Selenium Toolkit for .NET now provides a simple mechanism to add user-defined extensions to Selenium.

Some background

A user-extension for Selenium is a JavaScript file that becomes embedded into Selenium’s Test Runner.  Typically, the script extends Selenium’s core JavaScript to add new commands, but it also can be used to extend existing functionality, or add custom locator strategies.  Both Selenium IDE and RC allow extensions to be added.

For the purposes of this discussion, here’s a crude example of a selenium extension: 
Selenium.prototype.getMyValue = function(locator, text) {
    return locator;
};

The toolkit takes a straight forward approach to including extensions: it combines the files listed in the configuration file (in order of appearance) into a single file and then configures the Selenium RC to use it. 

Incidentally, if you ever need to verify that your extensions were loaded, you can simply view the JavaScript file at this url: http://localhost:4444/selenium-server/core/scripts/user-extensions.js

The ISelenium interface of the Selenium API does not directly expose a mechanism to execute custom commands.  Instead, we need to send our custom command using a command processor (ICommandProcessor), which isn’t exposed by default so a custom implementation of the ISelenium interface is required.  The Selenium documentation provides a pretty good overview of how to do this, and the remainder of this post demonstrates how to integrate this approach with the toolkit.

Create a customized ISelenium

One of the new features added to the toolkit in this release is the ability to supply your own mechanism for instantiating the ISelenium instance. The factory is a basic class with a Create method.  Simply implement the ISeleniumFactoryProvider interface and then wire it up into the configuration settings (see below).  If no setting is provided in the config, a default factory is used.

This example below shows a custom ISeleniumFactoryProvider that creates a customized ISelenium instance that exposes the ICommandProcessor:

namespace Custom
{
    using Selenium;
    using SeleniumToolkit.Core;

    public class SeleniumFactory : ISeleniumFactoryProvider
    {
        public ISelenium Create(string host,
                                int port,
                                string browserProfile,
                                string baseUrl)
         {
             ICommandProcessor processor = new HttpCommandProcessor(host, port, browserProfile, baseUrl);
             return new CustomSelenium(processor);       
         }
    }

    public class CustomSelenium : DefaultSelenium
    {
        public CustomSelenium(ICommandProcessor processor) 
            : base(processor)
        {
            CommandProcessor = processor
        }

        public ICommandProcessor CommmandProcessor
        {
            get;
            protected set;
        }
    }
}

Tweak your Settings

After you’ve compiled your custom factory, you’ll need to reference your JavaScript file in the userExtensions element and specify your custom factory using the factoryType attribute of the Selenium Node.

<Selenium
    factoryType="Custom.SeleniumFactory, CustomProject"
    >
   <userExtensions>
       <add name="example"
            path="myextension.js" />
   </userExtensions>
</Selenium>

Putting it all together

With the configuration settings in place, now all we need to do is cast the Browser.Current instance to our custom type.

namespace Custom.Test
{
    using NUnit.Framework;
    using Selenium;
    using SeleniumToolkit;

    [WebFixture]
    public class Example
    {
        [WebTest]
        public void ShowUsage()
        {
            CustomSelenium browser = Browser.Current as CustomSelenium;

            string[] inputArgs = { "Hello World" };
            string result = browser.CommandProcessor.DoCommand("getMyValue", inputArgs);
            Assert.AreEqual("Hello World", result);
        }
    }
}

Happy coding.

submit to reddit

Thursday, November 19, 2009

Selenium Toolkit for .NET 0.81 Now Available

I’m happy to announce the next release for the Selenium Toolkit for .NET is now available for download.  This release adds minor fixes to the runtime and enhanced configuration support.

New for this release

This release includes several new enhancements:

  • NUnit 2.5.2 Support
  • Custom Browser Profiles and Aliases
  • User Extensions support
  • Proxy Server support

NUnit 2.5.2 Support

This release represents an upgrade for the NUnit addin to latest version NUnit (2.5.2).  NUnit 2.5.2 includes several performance and user interface enhancements which improve the development experience, including data driven tests and source-code browser for exceptions.

As part of a dependency issue with the NUnit framework, addins are specific to the runtime they’re compiled against, so you must have NUnit 2.5.2 installed in order to use the addin.  If you have NUnit 2.4.8, you’ll have to upgrade.  If you haven’t been able to use the toolkit because you weren’t using NUnit 2.4.8, please download and send in some feedback.

Custom Browser Profiles and Aliases

One of the key goals of the toolkit is to minimize duplication and environment specific settings in your tests so that the impact of moving between environments is minimized.  The toolkit now supports the concept of browser aliases where custom profiles can be defined as a lookup table in the configuration settings.

Before:

[WebFixture]
public class ExampleTest
{
    [WebTest(DefaultBrowser=@"*custom \"C:\PathToFireFox\FireFox.exe\" -no-remote -profile \"C:\PathToProfile\"")]
    public void OpenCustomProfile()
    {
        // ....
    }
}

After:

The dependency on the physical folder path can now be externalized to the configuration file, which can be modified to suit each environment without having to alter the tests.

[WebFixture]
public void ExampleWithBrowserAlias
{
    [WebTest(DefaultBrowser="ff-profile-1")]
    public void OpenCustomProfile()
    {
        // ....
    }
}

And the configuration settings....

<configuration>
    <!-- snip -->

    <Selenium
        BrowserUrl="http://www.bryancook.net"
        >
        <browsers>
            <add key="ff-profile-1"
                 value="*custom &quot;C:\FireFoxPath&quot; -no-remote -profile &quot;PathToProfile&quot;"
                />
        </browsers>
    </Selenium>

</configuration>

User Extensions support

Selenium provides an extensibility model that allows you to extend its functionality through custom JavaScript files.  This release provides two key enhancements to enable this functionality:

  • Configuration element that allows you to specify JavaScript files and directories to be concatenated into the user-extensions.js file; and
  • Factory model that allows you to create your own implementations of the ISelenium interface.  A custom implementation allows you to execute your own custom commands, and will likely play an integral role in the WebDriver backed Selenium implementation planned for Selenium 2.0.

Expect a blog post soon that demonstrates this functionality, but in the meantime you can find details on the configuration settings here.

Proxy Server Support

While not as exciting or as interesting as custom user extensions, this release includes some additional configuration settings for users running Selenium-RC against a web-site that is only accessible through a proxy server.  See the configuration settings  for more details.

Download now

Enough already!  Go download the latest release and try it out.  As always, feedback is always welcome.

Happy coding.

submit to reddit

Monday, October 19, 2009

Configuring the Selenium Toolkit for Different Environments

Suppose you’ve written some selenium tests using Selenium IDE that target your local machine (http://localhost), but you’d like to repurpose the same tests for your QA, Staging or Production environment as part of your build process.  The Selenium Toolkit for .NET makes this really easy to change the target environment without having to touch your tests.

In this post, I’ll show you how to configure the Selenium Toolkit for the following scenarios:

  • Local Selenium RC / Local Web Server
  • Local Selenium RC / Remote Web Server
  • Remote Selenium RC / Remote Web Server

Running Locally

In this scenario, both the Selenium Remote Control Host (aka Selenium RC / Selenium Server) and the web site you want to test are running on your local machine.  This is perhaps the most common scenario for developers who develop against a local environment, though it also applies to your build server if the web server you want to test is also on that machine. 

Although this configuration is limited to running tests against the current operating system and installed browsers, it provides a few advantages to developers as they can watch the tests execute or set breakpoints on the server to assist in debugging.

This is the default configuration for the Selenium Toolkit for .NET – when the tests execute, the NUnit Addin will automatically start the Selenium RC process and shut it down when the tests complete.

Assuming you have installed the Selenium Toolkit for .NET, the only configuration setting you'll need to provide is the URL of the web site you want to test. In this example, we assume that http://mywebsite is running on the local web server.

<Selenium BrowserUrl="http://mywebsite" />

Running Tests against a Remote Web Server

In this scenario Selenium RC runs local, but web server is on a remote machine.  You’ll still see the browser executing the tests locally, but because the web-server is physically located elsewhere it’s not as easy to debug server-side issues.  From a configuration perspective, this scenario uses the same configuration settings as above, except the URL of the server is not local.

This scenario is typically used in a build server environment.  For example, the build server compiles and deploys the web application to a target machine using rsync and then uses Selenium to validate the deployment using a few functional tests.

Executing Tests in a Remote Environment / Selenium Grid

In this scenario your local test-engine executes your tests against a remote Selenium RC process.  While this could be a server where the selenium RC process is configured to run as a dedicated service, it’s more likely that you would use this configuration for executing your tests against a Selenium Grid.  The Selenium Grid server exposes the same API as the Selenium RC, but it acts as a broker between your tests and multiple operating systems and different browser configurations.

To configure the Selenium Toolkit to use a Selenium Grid, you’ll need to specify the location of the Grid Server and turn off the automatic start/stop feature:

<Selenium
     server="grid-server-name"
     port="4444"  
     BrowserUrl="http://mywebsite.com"
   />
   <runtime
        autoStart="false"
        />
</Selenium>

submit to reddit

Monday, September 21, 2009

About the Selenium Toolkit for .NET

As part of the development process my open source project, I’ll be using my blog to post updates.  So subscribe via RSS, by email, follow me on twitter, or just bookmark me.

The Selenium Toolkit for .NET is based on my experiences implementing Selenium for .NET based projects.  When I started this project, I set out with the goal to minimize the time investment needed for developers to come on board, so they could concentrate on developing and running tests sooner.  This has largely been realized by separating the test-framework plumbing from the tests using an nunit addin and streamlining the setup process by creating an installer package that contains several utilities in a single download.

One of the more interesting and useful features that has come out of that initial goal is the ability to configure the tests through configuration elements in the app.config.  This feature makes it easy to run slightly different configurations between developer machines and build server without having to alter the tests.  Beyond this feature, and what excites me most, is that the toolkit and its configuration are separate components from the nunit addin.  This division makes it possible to include addins for other testing frameworks such as MSTest, xUnit, mbUnit, etc when available.  In addition, the toolkit uses a provider model for creating selenium instances.  This extensibility model will hopefully lead to future versions of the toolkit with features such as proxy-server detection, embedded user-extensions and alternate user-defined implementations of the ISelenium interface.

On the NUnit addin side, I'm presently compiling against version 2.4.8 simply because it was the framework I started the project with.  Unfortunately, the current design of the addin has a dependency to a specific nunit assembly, which results in some runtime errors if a newer version of nunit is used.  I'll likely be moving to 2.5.2 within a week if I find the time to do some regression testing.  Down the road I might investigate changing the addin to take advantage of some of NUnit's newer features, such as the RowTest extension.

The installer is functional, but there's still work to be done.  For instance, I'd like to have the Selenium IDE silently install into Firefox as part of the overall installation, and I'd like to provide some examples and Visual Studio Templates included as well.  I'll likely be converting from the Visual Studio installer package to a WiX format, to provide greater flexibilty during the user-experience.  WiX projects can also be built from the command-line (whereas VS installer projects can't), which will help to automate the packaging process.

Currently, the toolkit is listed as "beta" only because I can't guarantee that some of the interfaces won't change.  If you're downloading and running for tests, you might have to update some assemblies or tweak app.config files, but the core logic for running the tests shouldn't change.

The toolkit is available here:  http://seleniumtoolkit.codeplex.com

Wednesday, September 16, 2009

Testing NUnit Addins from within NUnit

Injecting your code into someone else's container

Note: This post refers to an internal feature of the NUnit.Core library and cannot be guaranteed in future versions.

Yesterday I released my first open source project, Selenium Toolkit for .NET, if you’re into functional web-testing I highly recommend you check it out.  I’d like to share a piece of code from that project – it’s either the biggest hack I’ve ever done or pretty clever.  Let me know what you think.

I don't like manually doing things more than once if I have to. Ironically, while building a tool to help automate functional web testing, I found that I had to do a lot of manual verification despite all the unit tests that I had written for my components. It started to get pretty frustrating: make a small change to my addin, uninstall and reinstall it, then open and run my sample test-fixtures to see how the NUnit framework had interpreted my changes. If I was going anywhere with this project, this was going to slow me down.

Fortunately, while spelunking through the NUnit.Core library, I found a really useful utility class that the fit the bill nicely and worked out pretty well. The TestAssemblyBuilder uses the nunit internals to find all the tests in an assembly and put them into a single Suite for inspection, execution, etc.

namespace Example
{
    using NUnit.Core.Builders;   

    public class ExampleTest
    {
        [Test]
        public void CanGetTestCount()
        {
            TestAssemblyBuilder assemblyBuilder = new TestAssemblyBuilder();
            TestSuite suite = assemblyBuilder.Build("AssemblyName.dll", false);

            Assert.AreEqual(4, suite.TestCount, "Not all tests were found.");
        }
    }
}

What’s really interesting here is the TestAssemblyBuilder uses a singleton within the NUnit internals, CoreExtensions.Host, to resolve all the core components for building up the suite.  This object implements the IExtensionHost interface which is also used to install our addin:

public interface NUnit.Core.Extensibility.IAddin
{
    bool Install(IExtensionHost host);
}

With this singleton at our disposal this is a pretty powerful option as I can now inject my addin into the framework with any configuration or mock that I want and test without environment dependencies.  In this example, I’m able to test how many times my Selenium instance would be started without ever launching a java host or browser:

namespace SeleniumToolkit.NUnit.Tests
{
    using NUnit.Core.Builders;
    using Selenium;
    using SeleniumToolkit;
    
    [TestFixture]
    public class FixtureBuilderTests
    {
        [Test]
        public void When_Fixture_Owns_Session_SeleniumFactory_Should_Only_Create_Sessions_For_Fixtures()
        {
            // create config that influences how the addin will work inside NUnit
            SeleniumConfiguration config = new SeleniumConfiguration();
            config.AddinSettings.RecyclePerFixture = true;
            
            // create basic event listener and suite-builder for installation into addin
            var eventListener = new SeleniumEventListener(null); // null = no java host
            var suiteBuilder = new SeleniumTestFixtureBuilder(config);

            // mock out the factory that creates our selenium objects
            var factory = MockRepository.GenerateMock<ISeleniumFactoryProvider>();
            var selenium = MockRepository.GenerateMock<ISelenium>();

            // tell our mock'd factory to always return our mock selenium
            factory.Expect(f => f.Create(null,0,null,null)).IgnoreArguments()
                   .Return(selenium).Repeat.Any();

            // set our expectations for how many times selenium will start/stop
            selenium.Expect(s => s.Start()).Repeat.Times(3);
            selenium.Expect(s => s.Stop()).Repeat.Times(3);

            // inject our mock into the toolkit
            SeleniumFactory.Configure(config, factory);

            // install addin
            SeleniumNUnitAddin addin = new SeleniumNUnitAddin();
            addin.Install(CoreExtensions.Host, suiteBuilder, eventListener); // injection method

            // using installed addin, test construction of fixtures
            var assemblyBuilder = new TestAssemblyBuilder();
            TestSuite suite = assemblyBuilder.Build( 
                                               "NUnit.TestAssembly.FixtureScenario.dll", 
                                               false);                        

            // run our sample fixtures against our configured runtime
            suite.Run(eventListener);

            // verify our behavior is as expected
            selenium.VerifyAllExpectations();
        }
    }

}

I should point out here that I don’t have my addin installed in NUnit’s addin folder. In fact, because I’m manually injecting it into NUnit, installation isn’t necessary. I also discovered that having the addin installed introduced some unexpected behavior with the tests in a few places.

To ensure that I'm testing my addin in isolation, it's important to clean up the CoreExtensions singleton after each test. While the NUnit core provides a mechanism to remove items from its extension points, it requires that you pass in the instances you want to remove, which didn’t quite fit my needs.  I suppose I could have implemented equality comparisons in my extensions, but I opted for the hack ‘em out using reflection option. It’s gross, but it works:

public class AddinUtil
{
    public static void Uninstall()
    {
        IExtensionPoint eventListeners = CoreExtensions.Host.GetExtensionPoint("EventListeners");
        IExtensionPoint suiteBuilders = CoreExtensions.Host.GetExtensionPoint("SuiteBuilders");
        IExtensionPoint testBuilders = CoreExtensions.Host.GetExtensionPoint("TestCaseBuilders");

        RemoveExtension(typeof(SeleniumEventListener), eventListeners);
        RemoveExtension(typeof(SeleniumTestFixtureBuilder), suiteBuilders);
        RemoveExtension(typeof(SeleniumTestCaseBuilder), testBuilders);
    }

    private static void RemoveExtension(Type type, IExtensionPoint extensionPoint)
    {
        ArrayList items = GetInternalExtensions(extensionPoint);
        ArrayList toRemove = new ArrayList();

        foreach (object item in items)
        {
            if (type.IsAssignableFrom(item.GetType()))
            {
                    toRemove.Add(item);
            }
        }

        foreach (object item in toRemove)
        {
            items.Remove(item);
        }
    }

    private static ArrayList GetInternalExtensions(IExtensionPoint extensionPoint)
    {
        object extensions = extensionPoint.GetType()
					  .GetField("extensions", 
							BindingFlags.NonPublic | 
							BindingFlags.Public | 
							BindingFlags.Instance)
					  .GetValue(extensionPoint);
        return (ArrayList)extensions;
    }
}

Conclusion

This technique provides a brief glimpse of how to use automate testing nunit addins inside nunit using dependency injection.  I’m fairly certain that I will still have to manually verify the addin’s behaviour from time to time, but with this approach I hopefully won’t have to do it that often.

submit to reddit

Announcing Selenium Toolkit for .NET

I’m pleased to announce that I’ve released my first open source project!

The Selenium Toolkit for .NET contains a bundled installer for Selenium libraries (Selenium-RC, Selenium IDE and Selenium client library for .NET) and an NUnit Addin that makes getting started with Selenium easy.

More information can be found here:  http://seleniumtoolkit.codeplex.com/