DZone
Web Dev Zone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
  • Refcardz
  • Trend Reports
  • Webinars
  • Zones
  • |
    • Agile
    • AI
    • Big Data
    • Cloud
    • Database
    • DevOps
    • Integration
    • IoT
    • Java
    • Microservices
    • Open Source
    • Performance
    • Security
    • Web Dev
DZone > Web Dev Zone > Finish Him: Kill All the WebDriver C# Code

Finish Him: Kill All the WebDriver C# Code

An issue that nags a lot of WebDriver users is when your driver's executable stays in use, causing your builds to fail. Time to introduce a fatality.

Anton Angelov user avatar by
Anton Angelov
·
Oct. 21, 17 · Web Dev Zone · Tutorial
Like (3)
Save
Tweet
10.32K Views

Join the DZone community and get the full member experience.

Join For Free


Kill All WebDrivers

Most of my articles are about WebDriver. Today, I am going to write about a common problem that people usually hit. Have you experienced this? Your tests finish and then all of a sudden, the browser is still opened? The next time you try to clean the build folder, you cannot because the current driver's EXE is still in use. Such a pity. From now on, your builds start failing. Many people complain about the flakiness of WebDriver, and this is one of the reasons. Here, I am going to propose to you a solution: As they say in Mortal Kombat, "Finish Him!" (kill all of the processes).

Test C# Code

Once again, I will use one of my favorite test pages: Bing. Below, you can find the page object that we will use in the tests.

BingMainPage.Actions

public partial class BingMainPage {
	private readonly IWebDriver _driver;
	private readonly string _url = @"http://www.bing.com/";
	public BingMainPage(IWebDriver browser) = >_driver = browser;
	public void Navigate() = >_driver.Navigate().GoToUrl(_url);
	public void Search(string textToType) {
		SearchBox = textToType;
		GoButton.Click();
	}
}


BingMainPage.Elements

public partial class BingMainPage {
	public IWebElement GoButton = >_driver.FindElement(By.Id("sb_form_go"));
	public IWebElement ResultsCountDiv = >_driver.FindElement(By.Id("b_tween"));
	public string SearchBox {
		get = >_driver.FindElement(By.Id("sb_form_q")).Text;
		set = >_driver.FindElement(By.Id("sb_form_q")).SendKeys(value);
	}
}


BingMainPage.Asserts

public partial class BingMainPage {
	public void AssertResultsCount(string expectedCount) = >Assert.AreEqual(ResultsCountDiv.Text, expectedCount);
}


We use partial classes. You can read more about this modified/improved version of the pattern in my article Page Objects with Partial Classes and Properties: WebDriver C#.

Partial Page Objects in Tests

Nothing special, really. We initialize the driver for each test and then perform the test case. By the way, we can reuse the browser if it is started in the assembly initialize method. This way, the test run's speed will be significantly improved.

[TestClass]
public class BingTests {
	private IWebDriver _driver;
	[TestInitialize]
	public void TestInit() {
		_driver = new ChromeDriver();
		_driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(30);
	} [TestCleanup]
	public void TestCleanup() {
		_driver.Quit();
	} [TestMethod]
	public void SearchTextInBing_First() {
		var bingMainPage = new BingMainPage(_driver);
		bingMainPage.Navigate();
		bingMainPage.Search("Automate The Planet");
		bingMainPage.AssertResultsCount("236,000 RESULTS");
	}
}


However, imagine that we have instead of a single test, we have 2,000 tests — or even more. Yeah. I bet that you will hit the problem I mentioned earlier. How often you experience it depends on the driver type you use. Some are more stable than others. For example, I noticed that it occurs more often for InternetExplorerDriver and OperaDriver.

The Solution: Kill Them All

How to Use it in Tests?

[TestClass]
public class BingTests {
	private static IWebDriver _driver;
	[AssemblyInitialize]
	public static void AssemblyInitialize(TestContext testContext) {
		DisposeDriverService.TestRunStartTime = DateTime.Now;
		_driver = new ChromeDriver();
		_driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(30);
	} [AssemblyCleanup]
	public static void AssemblyCleanUp() {
		DisposeDriverService.FinishHim(_driver);
	} [TestMethod]
	public void SearchTextInBing_First() {
		var bingMainPage = new BingMainPage(_driver);
		bingMainPage.Navigate();
		bingMainPage.Search("Automate The Planet");
		bingMainPage.AssertResultsCount("236,000 RESULTS");
	}
}


Above, we reuse the driver instance for all tests in the current test run. Finally, when all of them finish, we finish the driver for good. Below, you will find how the magic works.

DisposeDriverService: Finish Him

public static class DisposeDriverService {
	private static readonly List < string > _processesToCheck = new List < string > {
		"opera",
		"chrome",
		"firefox",
		"ie",
		"gecko",
		"phantomjs",
		"edge",
		"microsoftwebdriver",
		"webdriver"
	};
	public static DateTime ? TestRunStartTime {
		get;
		set;
	}
	public static void FinishHim(IWebDriver driver) {
		driver ? .Dispose();
		var processes = Process.GetProcesses();
		foreach(var process in processes) {
			try {
				Debug.WriteLine(process.ProcessName);
				if (process.StartTime > TestRunStartTime) {
					var shouldKill = false;
					foreach(var processName in _processesToCheck) {
						if (process.ProcessName.ToLower().Contains(processName)) {
							shouldKill = true;
							break;
						}
					}
					if (shouldKill) {
						process.Kill();
					}
				}
			}
			catch(Exception e) {
				Debug.WriteLine(e);
			}
		}
	}
}


Our first job is to set the TestRunStartTime before the test execution. As you can find out above, we do that in the AssemblyInitialize method before any test is executed. Then we call the FinishHim method in the AssemblyCleanup after all tests. First, we give a chance of the current driver to dispose of itself. If any browsers or driver's processes are still present after that, we kill them.

But why do we need to set the TestRunStartTime then? Because you don't want to kill any browsers that weren't started from your tests. Because of that, for each process, we check its start time. If it was created after the test run started, we may potentially kill it. The second validation that we make is to find out if the process is a browser or driver. If it is, we kill it.

Download the full source code here.

csharp Testing Driver (software)

Published at DZone with permission of Anton Angelov, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • 11 Reasons To Use Selenium for Automation Testing
  • Why Great Money Doesn’t Retain Great Devs w/ Stack Overflow, DataStax & Reprise
  • How to Hash, Salt, and Verify Passwords in NodeJS, Python, Golang, and Java
  • Take Control of Your Application Security

Comments

Web Dev Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • MVB Program
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends:

DZone.com is powered by 

AnswerHub logo