我看到了一些使用Selenium WebDriver并行化嵌套循环网络压力测试的死实例怪怪的,简单的例子是,比如说,点击300个独特的页面,每个页面都有100个印象。
我正在“成功地”获得4-8个WebDriver实例,使用ThreadLocal<FirefoxWebDriver>来隔离每个任务线程,并在ParallelOptions实例上使用MaxDegreeOfParallelism来限制线程。我只对外部循环(页面集合)进行分区和并行化,并在每个分区的“长时间运行任务”方法的开头检查ThreadLocal<>容器上的ThreadLocal<>。为了便于以后的清理,我将每个新实例添加到由线程id键确定的ConcurrentDictionary中。
无论我使用什么并行化或分区策略,WebDriver实例偶尔都会执行以下操作之一:
当这两种情况都发生时,并行循环最终似乎注意到线程没有执行任何操作,并且产生了一个新的分区。如果n是允许的线程数,这将导致n个生产线程的时间仅为50-60%。
清理工作在最后仍然很好;可能有2n个开放浏览器,或者更多,但是生产性和非生产性的浏览器都会被清理干净。
有没有办法监视这些无用的WebDriver实例,以及( a)立即清除它们,再加上b)立即获得并行循环来替换任务段,而不是像现在这样落后几分钟?
发布于 2012-05-08 16:00:33
由于没有
OnReady事件,也没有IsReady属性,所以在创建每个实例之后,我通过休眠线程来解决这个问题。这样做似乎给了我100%持久的、功能良好的WebDriver实例。
多亏了您的建议,我在开源项目Webinator中实现了IsReady功能。如果需要,可以使用它,或者使用下面列出的代码。
我尝试过实例化25个实例,它们都是功能性的,因此我对算法非常有信心(我利用HtmlAgilityPack来查看元素是否存在,但为了简单起见,我将跳过它):
public void WaitForReady(IWebDriver driver)
{
var js = @"{ var temp=document.createElement('div'); temp.id='browserReady';" +
@"b=document.getElementsByTagName('body')[0]; b.appendChild(temp); }";
((IJavaScriptExecutor)driver).ExecuteScript(js);
WaitForSuccess(() =>
{
IWebElement element = null;
try
{
element = driver.FindElement(By.Id("browserReady"));
}
catch
{
// element not found
}
return element != null;
},
timeoutInMilliseconds: 10000);
js = @"{var temp=document.getElementById('browserReady');" +
@" temp.parentNode.removeChild(temp);}";
((IJavaScriptExecutor)driver).ExecuteScript(js);
}
private bool WaitForSuccess(Func<bool> action, int timeoutInMilliseconds)
{
if (action == null) return false;
bool success;
const int PollRate = 250;
var maxTries = timeoutInMilliseconds / PollRate;
int tries = 0;
do
{
success = action();
tries++;
if (!success && tries <= maxTries)
{
Thread.Sleep(PollRate);
}
}
while (!success && tries < maxTries);
return success;
}假设浏览器响应javascript函数并找到元素,那么它可能是一个可靠的实例,可以使用。
发布于 2012-07-20 19:23:56
我也有类似的问题。事实证明,WebDriver没有找到开放端口的最佳方法。正如所描述的这里,它在端口上获得一个系统范围的锁,找到一个开放端口,然后启动实例。这可能会使您尝试启动端口的其他实例挨饿。
我通过在ThreadLocal<IWebDriver>的委托中直接指定一个随机端口号来解决这个问题,如下所示:
var ports = new List<int>();
var rand = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);
var driver = new ThreadLocal<IWebDriver>(() =>
{
var profile = new FirefoxProfile();
var port = rand.Next(50) + 7050;
while(ports.Contains(port) && ports.Count != 50) port = rand.Next(50) + 7050;
profile.Port = port;
ports.Add(port);
return new FirefoxDriver(profile);
});这对我来说非常一致,尽管如果你最终使用列表中所有的50种都是未解决的问题,这是个问题。
https://stackoverflow.com/questions/10327095
复制相似问题