我有一些代码,如下所示。我正在尝试增加一个计数器并使其线程安全。 注意:我在这个方法中遗漏了不相关的代码。
public static class MyClass
{
private static int m_Counter;
public static int Counter
{
get { return m_Counter; }
}
public static string MyMethod(this IWebDriver self, string testname = null)
{
Console.WriteLine("Test name: " + testname + ". Before incrementing Counter: " + Counter.ToString());
Console.WriteLine("Test name: " + testname + ". Before incrementing m_Counter: " + m_Counter.ToString());
Interlocked.Increment(ref m_DownloadsCounter);
Console.WriteLine("Test name: " + testname + ". After incrementing Counter: " + Counter.ToString());
Console.WriteLine("Test name: " + testname + ". After incrementing m_Counter: " + m_Counter.ToString());
}
我认为使用 Interlocked 会使变量线程安全,因为这里显示的答案 之前的 StackOverflow 答案
它不起作用。也许是因为我的技术堆栈和独特的情况。我正在跨测试装置(不在测试装置内)并行执行 Selenium Webdriver 和 Nunit 测试。
例如,以下 2 个测试调用 MyMethod。
如果我并行执行这些测试,控制台将打印以下内容
Test name: SampleTest_DownloadAndEditFiles. Before incrementing Counter: 0
Test name: SampleTest_DownloadAndEditFiles. Before incrementing m_Counter: 0
Test name: SampleTest_DownloadAndEditFiles. After incrementing Counter: 1
Test name: SampleTest_DownloadAndEditFiles. After incrementing m_Counter: 1
Test name: demoFileDownloads. Before incrementing Counter: 1
Test name: demoFileDownloads. Before incrementing m_Counter: 1
Test name: demoFileDownloads. After incrementing Counter: 2
Test name: demoFileDownloads. After incrementing m_Counter: 2
我反而期待以下内容
Test name: SampleTest_DownloadAndEditFiles. Before incrementing Counter: 0
Test name: SampleTest_DownloadAndEditFiles. Before incrementing m_Counter: 0
Test name: SampleTest_DownloadAndEditFiles. After incrementing Counter: 1
Test name: SampleTest_DownloadAndEditFiles. After incrementing m_Counter: 1
Test name: demoFileDownloads. Before incrementing Counter: 0
Test name: demoFileDownloads. Before incrementing m_Counter: 0
Test name: demoFileDownloads. After incrementing Counter: 1
Test name: demoFileDownloads. After incrementing m_Counter: 1
我需要在代码中添加或删除什么?或者我需要放弃一切并使用不同的方法吗?
我不确定是否需要完整的堆栈跟踪来回答这个问题,但下面是该跟踪。这就是测试方法到达MyMethod的方式。
首先是基类
public class TestBase
{
Browser = new ChromeDriver(cService, new BaseChromeOptions(), commandTimeout);
}
接下来是测试课
[LocalSeleniumTestFixture(BrowserNames.Chrome)]
[LocalSeleniumTestFixture(BrowserNames.Firefox)]
[TestFixture]
public class MyTests : TestBase
{
public MyTests(string browserName) : base(browserName) { }
[Test]
public void demoFileDownloads()
{
Browser.Navigate().GoToUrl("https://www.selenium.dev/selenium/web/downloads/download.html");
IWebElement btn1 = Browser.FindElement(By.Id("file-1"));
btn.ClickAndWaitForDownload(Browser, "demoFileDownloads");
}
}
测试类调用 WebElementExtensions
public static class WebElementExtensions
{
public static string ClickAndWaitForDownload(this IWebElement self, IWebDriver Browser, string testname = null)
{
self.Click();
return Browser.MyMethod(testname);
}
}
借助
Concurrent
系列,您可以实现您想要的目标。例如:
public static class MethodCounter
{
private static ConcurrentDictionary<string, int> m_counters = new ConcurrentDictionary<string, int>();
public static ConcurrentDictionary<string, int> Counters
{
get { return m_counters; }
}
public static void Increment(string methodName)
{
m_counters.AddOrUpdate(methodName, 1, (key, existingValue) => existingValue + 1);
}
public static int GetCount(string methodName)
{
if (m_counters.TryGetValue(methodName, out var count))
{
return count;
}
return 0;
}
}
增加它:
MethodCounter.Increment(testname);
通过以下方式访问它:
MethodCounter.GetCount(testname);