0

How can I set up a class library containing browser-based integration tests to have different configuration options based on the build configuration / environment combo?

I have a test class library in .NET that has a mix of unit tests, integration tests, and some new acceptance style Selenium tests. In the past for a web project I have done config file replacement so I can specify a different set of configuration values for different build configurations (Dev / Stage / Release, etc...). I also know that I can store settings used by the test library int the App.config file so I assume something like this is possible for a class library as well but have not been able to find any answers.

For example, when I run the Selenium acceptance tests on my local development machine, I have a specific localhost URL for the website Selenium is being run against (and I run a Debug build), but this URL differs in my dev (and other environments).

How can I achieve this?

I have done some research on this, but nothing specifically answered this question. Many of the other answers I've found have to do with unit testing the config file (Unit testing the app.config file with NUnit) or modifying the config file at runtime, which is not what I want. The only one that came close was this question here: How do I run my NUnit test cases using Selenium to run against different environments? but the answer given is a lot of custom code, that would need to be maintained if new build configurations or environments are added which is not what I want. I would like (if possible) a configuration file replacement solution so this scales and can be run by me on my machine, by a QA who doesn't have studio, or by a CI server like TeamCity as part of a post-build process. In addition, a config file replacement will also keep the test library consistent with the way the rest of the code base is set up.

It is important to note that I don't necessarily want to store values needed by the code I'm testing because these are browser-based acceptance tests. I am merely concerned with storing values that control the execution of my test suite and affect how my tests interact with the site (not performing operations that would modify a production database when running the tests on live for example).

Here is a code snippet to help illustrate how this would be used:

Private _baseUrl As String
Private _driver As IWebDriver

<Setup()> _
Protected Overridable Sub Setup()
    'This config call will return a different value based on the project build (Dev / Stage / Live)
    _baseUrl = ConfigurationManager.AppSettings("BaseWebUrl")
    Dim options As New IE.InternetExplorerOptions()
    options.IgnoreZoomLevel = True
    _driver = New IE.InternetExplorerDriver("PathToIEExecutable", options)
End Sub

<TearDown()> _
Protected Overridable Sub TearDown()
    _driver.Quit()
End Sub

<Test(), Category("Acceptance")> _
Public Sub HomePage_NewUserVisit_ShouldSeeWelcomeMessage()
    Me.Driver.Navigate().GoToUrl(_baseUrl)

    Me.Driver.VerifyElementPresent("//body/div[@id='welcome-message']")

    Assert.AreEqual("This Website R0xor3s - Welcome", Me.Driver.Title, "Unexpected Title.")
End Sub

Protected ReadOnly Property Driver As IWebDriver
    Get
        Return _webDriver
    End Get
End Property

I am using NUnit (2.6.3) and Selenium WebDrivers (2.4.1)

Community
  • 1
  • 1
xDaevax
  • 2,012
  • 2
  • 25
  • 36
  • You could probably use Mock or Fakes to inject a replacement class for ConfigurationManager within your tests ? – PhillipH Aug 14 '14 at 14:27
  • @PhillipH I'm not sure I follow *how* you are suggesting to implement that, can you elaborate a bit more? Moq is a tool I regularly use for unit tests but in this instance it doesn't seem to get around the conditional building of a mocked object based on environment. Wouldn't that approach still require code maintenance whenever a new build configuration was introduced? – xDaevax Aug 18 '14 at 15:11
  • With Microsoft Fakes you can add a substitute class method/property for a closed class (i.e. where you can't change the source code to use dependency injection) in your unit test. This subordinates the standard .net loader and returns the value you specify in your Fake when the loader encounters the faked-out class in closed code. It is illustrated here http://msdn.microsoft.com/en-GB/library/hh549175.aspx. I've not done it with ConfigurationManager class but it should work. It means you dont have a new config file per test, but can change the values returned on a case-by-case basis. – PhillipH Aug 18 '14 at 19:12
  • @PhillipH That makes sense, but I still don't see how I'll get around having a case or if logic to say: `if dev, return x, if stage return y` which I was hoping to avoid by using the config replacement (since at build time the correct config for the environment will be the only config available). In your example case, I could avoid config manager all together (which I'm not opposed to) but then I would have to maintain that code (which I'd rather not have to do). Does that make sense? – xDaevax Aug 18 '14 at 19:29
  • Yes - but if you have some Test specific configuration data pass it through the Test Context mechanism that MS Test uses. This means you can run the same test with multiple input parameters (config substitute values) simply by changing the test context you pass in. This should give you what you need ? – PhillipH Aug 18 '14 at 20:16
  • @PhillipH Well, I am using NUnit (not MSTest), but it does has a construct for different test cases with input parameters. As far as I know however, there is no way to pass in the current build configuration as an argument to trigger different sets of values off of. Are you able to post a code example of what you mean? Maybe that will help me get a better understanding of what you are saying. Also, thanks for the effort on this, seems like not many people have anything to say about this topic. – xDaevax Aug 18 '14 at 20:23
  • The data driving of MS tests is covered here http://msdn.microsoft.com/en-us/library/ms182527.aspx. In a VS.net test run (which I can execute on the command line as well) I can specify the source of the data that will be passed in the TestContext. There is no specific relationship to the Debug/Test configurations of VS.net (of which there can be many). Its difficult to post code because its all just VS.net / MS Test configuration settings. The basic chain would be 1) Use Fakes to substitute the use of Config files in your test 2) Use TestContext to supply the substitute values used in the Fake – PhillipH Aug 18 '14 at 20:43
  • 3) Use MS Test configuration and/or command line to pass different TestContext file into the test based on which data you want the test to use in (1) + (2). 4) Which configuration of the test you want to run isn't directly linked to which compilation option you used to build (Debug\Release\CustomConfig etc). Hope this helps. It seems all the ingredients are there to get where you want to go, but its an application lifecycle maintenance (ALM) issue from thereon. – PhillipH Aug 18 '14 at 20:46
  • @PhillipH Thanks for your input, but at this point I can't afford to swtich from NUnit to MSTest and build a database to store these values. Too many existing tests that work fine with mocks and fakes to go back and change. Further, it's not that I don't *want* to be tied to my build configuration / environment, but rather the opposite that I do want it to be based solely on that (if possible). – xDaevax Aug 18 '14 at 20:50
  • why not use transformation feature in configuration file? [Transform appSettings from external file after merge][1] [1]: http://stackoverflow.com/questions/22509321/transform-appsettings-from-external-file-after-merge/29138386#29138386 – Rock Jing Mar 19 '15 at 06:44

0 Answers0