
*Moved to: http://fluentbytes.com/how-to-reuse-your-browser-window-between-tests-in-codedui/
When you run automated test scenario’s against web applications, it often takes a lot of time to get to the initial state of your application from where you want to run a test scenario.
When you run a standard CodeUI test and use the BrowserWindow class to start the web browser, it will automatically close the browser when the test method is done. This is nice an clean and great if you don’t want previous tests to potentially influence your test run. So the fact that this is the default makes a lot of sense.
A question that I get asked rather often is, if there is a way to reuse the browser window across different test methods. The answer is yes! this is possible although not immediately apparent how.
so CodedUI uses a Playback Engine that gets initialized when you run the first test and that get’s cleaned up when you are done. this is done implicit by MSTest when it sees the [CodedUITest] attribute on top of your test class. This is important to know, because when the Playback Engine is not initialized and you use the CodedUI object model like for instance the BrowserWindow class, you will get error messages like:
Microsoft.VisualStudio.TestTools.UITest.Extension.TechnologyNotSupportedException: The browser is currently not supported.
This even happens when you use a plain vanilla BrowserWindow.Launch call.
So why is this important to know? Well when you want to start the BrowserWindow once for all tests, it is required to start the browser window prior to your test method. So for that you might want to leverage the [ClassInitialize] attribute. This can be placed on a static method that has one parameter TestContext. this method will be called only once for your test class and is therefore ideal to start the Browser Window. The issue is that when this method is called the playback engine is not initialized yet, so therefore we need to initialize it ourselves. This is simple to do, by just calling the method Initialize() on the Playback object.
But there are some more issues that make a simple and obvious solution unusable. (e.g. Create an instance of the BrowserWindow in the Initialize and then reuse it in every method) The Issue is that the Test Engine will run each test method potentially on another Thread. When you start the BrowserWindow in the initialize and then use it in every test method you would access the BrowserWindow class instance from different threads and apparently this results in unexpected behavior of the BrowserWindow class. So what we need to do is initialize a new BrowserWindow class for each test method while still reusing the same browser instance. This is possible, but the way to achieve this is by using the Process class of the BrowserWindow.
What you do is you initialize the browser once in the Initialize method of your class and you then get the process class for that instance of the browser. Next in each test method you create a new instance of the BrowserWindow class but there we use the FromProcess() method in stead of the Launch Method. This will wrap a new Instance of the BrowserWindow on the current process, hence reusing the browser session.
There is one final thing we need to fix, before this works. That is that after a test method completes the Browser Window is cleaned up automatically. This can be prevented by setting the property CloseOnPlaybackCleanup to false on the initial instance of the BrowserWindow we create.
So to conclude you can have a look at the code sample below, where you can see the steps you need to take to reuse the browser window cross multiple test methods in your test class. I created a very simple test that reuses the browser that browses to the Bing home page and searches for a search term.
[CodedUITest] public class ReuseTheBrowser { static Process proc = null; [ClassInitialize] public static void initializeTest(TestContext context) { Playback.Initialize(); var _bw = BrowserWindow.Launch(new Uri("http://www.bing.com")); proc = _bw.Process; _bw.CloseOnPlaybackCleanup = false; } [ClassCleanup] public static void CleanUp() { BrowserWindow _bw = BrowserWindow.FromProcess(proc); _bw.Close(); } [TestMethod] public void CodedUITestMethodFirstTest() { BrowserWindow _bw = BrowserWindow.FromProcess(proc); _bw.NavigateToUrl(new Uri("http://www.bing.com")); EnterSearchValue(_bw, "Pluralsight CodedUI training"); ClickSearch(_bw); } [TestMethod] public void CodedUITestMethodSecondTest() { BrowserWindow _bw = BrowserWindow.FromProcess(proc); _bw.NavigateToUrl(new Uri("http://www.bing.com")); EnterSearchValue(_bw, "Reuse BrowserWindow cross tests"); ClickSearch(_bw); } [TestMethod] public void CodedUITestMethodThirdTest() { BrowserWindow _bw = BrowserWindow.FromProcess(proc); _bw.NavigateToUrl(new Uri("http://www.bing.com")); EnterSearchValue(_bw, "CodedUI without UIMap"); ClickSearch(_bw); } private static void ClickSearch(BrowserWindow _bw) { HtmlInputButton searchButton = new HtmlInputButton(_bw); searchButton.SearchProperties.Add(HtmlInputButton.PropertyNames.Id, "sb_form_go"); Mouse.Click(searchButton); } private static void EnterSearchValue(BrowserWindow _bw, string value) { HtmlEdit searchBox = new HtmlEdit(_bw); searchBox.SearchProperties.Add(HtmlEdit.PropertyNames.Id, "sb_form_q"); searchBox.Text = value; } }
Enjoy!
Marcel
Follow my new blog on http://fluentbytes.com