From f98a4aa44bfd1fb5f2ceb8e18414571bd8d84ccc Mon Sep 17 00:00:00 2001 From: Simonov Mihail Date: Thu, 4 Apr 2024 10:48:14 +0500 Subject: [PATCH] Add IWebDriverDisposer --- Selone.Tests/Browsers/BrowserPool.cs | 29 +++++--- Selone.Tests/Selone.Tests.csproj | 4 +- .../Tests/WebDrivers/WebDriverPoolTests.cs | 68 ++++++++++++++++--- Selone/Selone.csproj | 2 +- Selone/WebDrivers/IWebDriverDisposer.cs | 8 +++ Selone/WebDrivers/IWebDriverKeyedPool.cs | 2 +- Selone/WebDrivers/WebDriverDisposer.cs | 19 ++++++ Selone/WebDrivers/WebDriverKeyedPool.cs | 4 +- Selone/WebDrivers/WebDriverPool.cs | 15 ++-- 9 files changed, 124 insertions(+), 27 deletions(-) create mode 100644 Selone/WebDrivers/IWebDriverDisposer.cs create mode 100644 Selone/WebDrivers/WebDriverDisposer.cs diff --git a/Selone.Tests/Browsers/BrowserPool.cs b/Selone.Tests/Browsers/BrowserPool.cs index ef979c7..5d2a5b4 100644 --- a/Selone.Tests/Browsers/BrowserPool.cs +++ b/Selone.Tests/Browsers/BrowserPool.cs @@ -6,21 +6,30 @@ namespace Kontur.Selone.Tests.Browsers { public static class BrowserPool { - public static readonly ChromeDriverFactory ChromeDriverFactory = new ChromeDriverFactory(new ChromeDriverFactoryConfiguration - { - WindowSize = new WindowSize {Width = 1024, Height = 768} - }); + public static readonly ChromeDriverFactory ChromeDriverFactory = new ChromeDriverFactory( + new ChromeDriverFactoryConfiguration + { + WindowSize = new WindowSize {Width = 1024, Height = 768} + }); - public static readonly InternetExplorerDriverFactory InternetExplorerDriverFactory = new InternetExplorerDriverFactory(new InternetExplorerDriverFactoryConfiguration - { - DriverDirectoryPath = @"C:\browsers\IE" - }); + public static readonly InternetExplorerDriverFactory InternetExplorerDriverFactory = + new InternetExplorerDriverFactory(new InternetExplorerDriverFactoryConfiguration + { + DriverDirectoryPath = @"C:\browsers\IE" + }); private static readonly DelegateWebDriverCleaner cleaner = new DelegateWebDriverCleaner(x => x.ResetWindows()); + public static readonly IWebDriverDisposer DriverDisposer = new WebDriverDisposer(x => + { + x.Close(); + x.Quit(); + x.Dispose(); + }); + public static readonly IWebDriverKeyedPool Instance = new WebDriverKeyedPool() - .Register(Browser.Chrome, ChromeDriverFactory, cleaner) - .Register(Browser.Ie, InternetExplorerDriverFactory, cleaner); + .Register(Browser.Chrome, ChromeDriverFactory, cleaner, DriverDisposer) + .Register(Browser.Ie, InternetExplorerDriverFactory, cleaner, DriverDisposer); } } \ No newline at end of file diff --git a/Selone.Tests/Selone.Tests.csproj b/Selone.Tests/Selone.Tests.csproj index 2b7867b..670073d 100644 --- a/Selone.Tests/Selone.Tests.csproj +++ b/Selone.Tests/Selone.Tests.csproj @@ -1,6 +1,5 @@  - net45;netcoreapp3.1 Kontur.Selone.Tests Kontur Kontur @@ -8,6 +7,7 @@ Kontur.Selone.Tests False latest + net6.0 ..\Build\Selone.Tests\ @@ -20,6 +20,8 @@ + + diff --git a/Selone.Tests/Tests/WebDrivers/WebDriverPoolTests.cs b/Selone.Tests/Tests/WebDrivers/WebDriverPoolTests.cs index 3549b2a..8196138 100644 --- a/Selone.Tests/Tests/WebDrivers/WebDriverPoolTests.cs +++ b/Selone.Tests/Tests/WebDrivers/WebDriverPoolTests.cs @@ -1,7 +1,10 @@ -using System.Threading; +using System.Linq; +using System.Threading; using Kontur.Selone.Extensions; using Kontur.Selone.Tests.Browsers; +using Kontur.Selone.Tests.Browsers.Factories; using Kontur.Selone.WebDrivers; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; using OpenQA.Selenium; @@ -12,7 +15,8 @@ public class WebDriverPoolTests [Test] public void Test() { - var webDriverPool = new WebDriverPool(BrowserPool.ChromeDriverFactory, new DelegateWebDriverCleaner(x => x.ResetWindows())); + var webDriverPool = new WebDriverPool(BrowserPool.ChromeDriverFactory, + new DelegateWebDriverCleaner(x => x.ResetWindows()), BrowserPool.DriverDisposer); using (var pooled = webDriverPool.AcquireWrapper()) { var webDriver = pooled.WrappedDriver; @@ -39,19 +43,67 @@ public void Create_New_WebDriver_Instance_When_Previous_Was_Disposed() { x.ResetWindows(); x.Quit(); - })); - + }), BrowserPool.DriverDisposer); + var webDriver = webDriverPool.Acquire(); - var sessionId1 = ((IHasSessionId)webDriver).SessionId; + var sessionId1 = ((IHasSessionId) webDriver).SessionId; webDriverPool.Release(webDriver); webDriver = webDriverPool.Acquire(); - var sessionId2 = ((IHasSessionId)webDriver).SessionId; + var sessionId2 = ((IHasSessionId) webDriver).SessionId; webDriverPool.Release(webDriver); - + Assert.AreNotEqual(sessionId1, sessionId2); - + webDriverPool.Clear(); } + + private IWebDriverPool InitWebDriverPool() + { + using var sp = new ServiceCollection() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton(_ => new DelegateWebDriverCleaner(x => x.ResetWindows())) + .AddSingleton(_ => new WebDriverDisposer(x => + { + x.Close(); + x.Quit(); + x.Dispose(); + })).BuildServiceProvider(); + + return sp.GetRequiredService(); + } + + [Test] + public void CorrectReusedDrivers_AndDispose() + { + var driverPool = InitWebDriverPool(); + + var firstUsingDrivers = new[] {driverPool.Acquire(), driverPool.Acquire()}; + foreach (var driver in firstUsingDrivers) + { + driver.Navigate().GoToUrl("https://kontur.ru"); + driverPool.Release(driver); + } + + var secondUsingDrivers = new[] {driverPool.Acquire(), driverPool.Acquire()}; + foreach (var driver in secondUsingDrivers) + { + driver.Navigate().GoToUrl("https://kontur.ru/press/news"); + driverPool.Release(driver); + } + + Assert.Multiple(() => + { + Assert.That( + firstUsingDrivers.Select(x => ((IHasSessionId) x).SessionId), + Is.EquivalentTo( + secondUsingDrivers.Select(x => ((IHasSessionId) x).SessionId)) + ); + Assert.DoesNotThrow(() => driverPool.Clear()); + Assert.IsTrue(firstUsingDrivers.All(x=> ((IHasSessionId) x).SessionId is null)); + }); + } } } \ No newline at end of file diff --git a/Selone/Selone.csproj b/Selone/Selone.csproj index b539de5..2b7b1ea 100644 --- a/Selone/Selone.csproj +++ b/Selone/Selone.csproj @@ -1,6 +1,6 @@  - net45;netstandard2.0 + net45;net5.0;net6.0;net7.0;netstandard2.0 Kontur.Selone Kontur Kontur diff --git a/Selone/WebDrivers/IWebDriverDisposer.cs b/Selone/WebDrivers/IWebDriverDisposer.cs new file mode 100644 index 0000000..e22b4d0 --- /dev/null +++ b/Selone/WebDrivers/IWebDriverDisposer.cs @@ -0,0 +1,8 @@ +using OpenQA.Selenium; + +namespace Kontur.Selone.WebDrivers; + +public interface IWebDriverDisposer +{ + void Dispose(IWebDriver webDriver); +} \ No newline at end of file diff --git a/Selone/WebDrivers/IWebDriverKeyedPool.cs b/Selone/WebDrivers/IWebDriverKeyedPool.cs index 52c5292..7de9d35 100644 --- a/Selone/WebDrivers/IWebDriverKeyedPool.cs +++ b/Selone/WebDrivers/IWebDriverKeyedPool.cs @@ -4,7 +4,7 @@ namespace Kontur.Selone.WebDrivers { public interface IWebDriverKeyedPool { - IWebDriverKeyedPool Register(TKey key, IWebDriverFactory factory, IWebDriverCleaner cleaner); + IWebDriverKeyedPool Register(TKey key, IWebDriverFactory factory, IWebDriverCleaner cleaner, IWebDriverDisposer disposer); IWebDriver Acquire(TKey key); IPooledWebDriver AcquireWrapper(TKey key); void Release(IWebDriver webDriver); diff --git a/Selone/WebDrivers/WebDriverDisposer.cs b/Selone/WebDrivers/WebDriverDisposer.cs new file mode 100644 index 0000000..102cfef --- /dev/null +++ b/Selone/WebDrivers/WebDriverDisposer.cs @@ -0,0 +1,19 @@ +using System; +using OpenQA.Selenium; + +namespace Kontur.Selone.WebDrivers; + +public class WebDriverDisposer : IWebDriverDisposer +{ + private readonly Action disposeAction; + + public WebDriverDisposer(Action disposeAction) + { + this.disposeAction = disposeAction; + } + + public void Dispose(IWebDriver webDriver) + { + disposeAction?.Invoke(webDriver); + } +} \ No newline at end of file diff --git a/Selone/WebDrivers/WebDriverKeyedPool.cs b/Selone/WebDrivers/WebDriverKeyedPool.cs index 44b0d9b..3e79525 100644 --- a/Selone/WebDrivers/WebDriverKeyedPool.cs +++ b/Selone/WebDrivers/WebDriverKeyedPool.cs @@ -9,9 +9,9 @@ public class WebDriverKeyedPool : IWebDriverKeyedPool private readonly ConcurrentDictionary pools = new ConcurrentDictionary(); private readonly ConcurrentDictionary acquired = new ConcurrentDictionary(); - public IWebDriverKeyedPool Register(TKey key, IWebDriverFactory factory, IWebDriverCleaner cleaner) + public IWebDriverKeyedPool Register(TKey key, IWebDriverFactory factory, IWebDriverCleaner cleaner, IWebDriverDisposer disposer) { - if (!pools.TryAdd(key, new WebDriverPool(factory, cleaner))) + if (!pools.TryAdd(key, new WebDriverPool(factory, cleaner, disposer))) { throw new Exception($"WebDriverFactory for key '{key}' already registered"); } diff --git a/Selone/WebDrivers/WebDriverPool.cs b/Selone/WebDrivers/WebDriverPool.cs index 5c4ab70..e9511c5 100644 --- a/Selone/WebDrivers/WebDriverPool.cs +++ b/Selone/WebDrivers/WebDriverPool.cs @@ -8,13 +8,19 @@ public class WebDriverPool : IWebDriverPool { private readonly IWebDriverFactory factory; private readonly IWebDriverCleaner cleaner; + private readonly IWebDriverDisposer driverDisposer; private readonly ConcurrentQueue queue = new ConcurrentQueue(); private readonly ConcurrentDictionary acquired = new ConcurrentDictionary(); - public WebDriverPool(IWebDriverFactory factory, IWebDriverCleaner cleaner) + public WebDriverPool( + IWebDriverFactory factory, + IWebDriverCleaner cleaner, + IWebDriverDisposer driverDisposer + ) { this.factory = factory; this.cleaner = cleaner; + this.driverDisposer = driverDisposer; } public IWebDriver Acquire() @@ -36,7 +42,7 @@ public void Clear() { while (queue.TryDequeue(out var webDriver)) { - webDriver.Dispose(); + driverDisposer.Dispose(webDriver); } } @@ -51,12 +57,13 @@ private void ReleaseInternal(IWebDriver webDriver) { if (!acquired.TryRemove(webDriver, out var dummy)) { - throw new Exception($"WebDriver {webDriver.GetType().Name} was not taken from the pool or already released"); + throw new Exception( + $"WebDriver {webDriver.GetType().Name} was not taken from the pool or already released"); } cleaner?.Clear(webDriver); - if (((IHasSessionId)webDriver).SessionId != null) + if (((IHasSessionId) webDriver).SessionId != null) { queue.Enqueue(webDriver); }