使用 chrome 和 selenium 进行网络节流

Network throttling with chrome and selenium

Google Chrome 38新推出"Device Mode & Mobile Emulation" functionality in devtools. In addition to choosing a device for emulation, it is also possible to emulate different network conditions:

Optimizing your site's performance under varying network conditions is a key aspect of developing for a mobile audience.

Device mode's network conditioning allows you to test your site on a variety of network connections, including Edge, 3G, and even offline. Select a connection from the preset dropdown to apply network throttling and latency manipulation.

例如,我们可以将其设置为像过去一样 - GPRS 50 Kbps:

现在我们有了一个很好的用例 - 我们有一个用于网络速度测试的内部应用程序。而这个新的仿真功能对于手动测试非常有帮助。但是,我们希望将其自动化。

问题是:

是否可以在指定的网络条件下通过 selenium 启动 chrome?它可以通过 chrome 首选项或 command-line 参数来控制吗?


simulate slow internet connection 当然有多个选项,但问题具体是关于 chrome+selenium。

不,无法控制Network Connectivity Emulation through Chrome preferences or command-line arguments. Network Connectivity Emulation is part of the build-in Chrome debugger. One way way in solving this is to control the debugger. This can be done via an extension or by directly controlling the debugger, see explanation. However, this will not work with WebDriver. The reason for this is that there can only be one "debug" session and WebDriver is already using it, see explanation。由于没有public界面,也无法通过WebDriver来控制。

Device Mode & Mobile Emulation which is also part of the build-in debugger, there is a public interface (details),因此可以控制。这可以通过 WebDriver Capabilities 来完成。两个选项 1) 指定设备名称 2) 输入您自己的参数(受限)。

虽然这是一个非常受欢迎和有用的功能,但对于严肃的测试,我认为传统的网络模拟方法仍然是可行的方法。

除了已经链接的解决方案之外,我还知道 2 个解决方案 - Charles web proxy (very useful tool - commercial) and implementing your own recipe using Linux Traffic Control (e.g. see chapter 6 of LAMPe2e)。

通过干扰网络连接而不是浏览器,您可以独立于所使用的浏览器来正确衡量影响。

您为什么只想使用 Chrome 功能?

API 控制网络仿真 were added to ChromeDriver. And should be available for quite a while now. According to comment 在链接问题中你应该使用至少 2.26 版本因为一些错误修复。

根据 Selenium changelog 绑定可用于以下语言:

  • JavaScript 从版本 3.4.0 开始 (commit)
  • Python 从版本 3.5.0 开始 (commit)
  • Ruby 版本 3.11.0 (commit)
  • C# 版本 4 (commit)

如果您需要其他语言的这些绑定,您可能应该打开 issue/contribute 类似于上述之一的实现。

Python 中的示例用法如下:

driver.set_network_conditions(
    offline=False,
    latency=5,  # additional latency (ms)
    download_throughput=500 * 1024,  # maximal throughput
    upload_throughput=500 * 1024)  # maximal throughput

Selenium (C#) 似乎即将推出。提交时间为 01/28/2018:

https://github.com/SeleniumHQ/selenium/blob/ef156067a583fe84b66ec338d969aeff6504595d/dotnet/src/webdriver/Chrome/ChromeNetworkConditions.cs

事实上,最新的 C# Selenium (3.11) 添加了 NetworkConditions。现在你可以像这样使用它了:

     var driver = new ChromeDriver(pathToDriver);
     driver.NetworkConditions = new ChromeNetworkConditions()
     {  DownloadThroughput = 5000, UploadThroughput = 5000, Latency = TimeSpan.FromMilliseconds(5) };

问题是由于 bug

还不能用

https://github.com/SeleniumHQ/selenium/issues/5693

因此 .Net 人员将不得不等到 3.12 Selenium 发布。

您可以使用此方法运行您在指定网络条件下的测试用例

protected void networkThrotting() throws IOException {
  Map map = new HashMap();
  map.put("offline", false);
  map.put("latency", 5);
  map.put("download_throughput", 500);
  map.put("upload_throughput", 1024);


  CommandExecutor executor = ((ChromeDriver)driver).getCommandExecutor();
  Response response = executor.execute(
        new Command(((ChromeDriver)driver).getSessionId(),    "setNetworkConditions", ImmutableMap.of("network_conditions", ImmutableMap.copyOf(map)))
  );
}

我知道这是一个老问题,但我最近不得不解决这个问题,并且此页面出现在我 Google 搜索的顶部。以下是我在 C# 中的主要部分。希望这对以后的人有帮助。

var networkConditions = new ChromeNetworkConditions();
networkConditions.Latency = new TimeSpan(150);
networkConditions.IsOffline = false;
networkConditions.DownloadThroughput = 120 * 1024;
networkConditions.UploadThroughput = 150 * 1024;
Driver.NetworkConditions = networkConditions;

以下问题现已在 this commit

中得到修复

对于像我这样在 C# 世界中想知道为什么 upload/download 吞吐量没有按预期工作的人来说,这些属性的工具提示似乎被错误标记了。工具提示指出数据速率是以 kb/s 为单位测量的,但根据我自己的经验,它实际上是每秒字节数,所以如果你想使用更熟悉的测量方法,如 Mbps,你必须乘以 125,000:

int latencyInMilliseconds = 20;
long downloadLimitMbps = 20;
long uploadLimitMbps = 5;
_driver.NetworkConditions = new ChromeNetworkConditions()
{
    Latency = new TimeSpan(0, 0, 0, 0, latencyInMilliseconds),
    DownloadThroughput = downloadLimitMbps * 125000, // Mbps to bytes per second
    UploadThroughput = uploadLimitMbps * 125000, // Mbps to bytes per second
    IsOffline = false,
};

在我的测试中使用这些设置并查看网络流量 运行 我可以看到它们正好导致 20Mbps 下降和 5Mbps 上升。

让我们考虑两种不同的方法,

一个我们可以限制整个网络,一个我们可以指定具体限制哪些网络请求。

方法 1:限制整个网络

const { Builder } = require("selenium-webdriver")

async function throttleNetwork() {
  let driver = await new Builder().forBrowser("chrome").build();

  await driver.setNetworkConditions({
    offline: false,
    latency: 5000, // Additional latency (ms).
    download_throughput: 50 * 1024, // Maximal aggregated download throughput.
    upload_throughput: 50 * 1024, // Maximal aggregated upload throughput.
  });

  driver.get("http://www.google.com/");
}

感谢 Yaroslav 指出提交。

这有一个缺点,我们无法指定要限制的特定网络请求,而其余的则不受限制。

让我们在下一个方法中解决这个缺点。

方法 2:限制特定网络请求

这里我们将使用来自 requestly called Requestly for Selenium 的 npm 包。

我们需要先在他们的 client application 中创建规则,然后通过创建共享列表来获取 link。

例如,让我们将网络请求限制到 google.com

require("chromedriver");
const { Builder } = require("selenium-webdriver");
const chrome = require("selenium-webdriver/chrome");
const {
  getRequestlyExtension,
  importRequestlySharedList,
} = require("@requestly/selenium");

const sharedListUrl = "YOUR_SHARED_LIST_LINK_HERE" // For example, use "https://app.requestly.io/rules/#sharedList/1631611216670-delay"

async function throttleGoogle() {
  const options = new chrome.Options().addExtensions(
    getRequestlyExtension("chrome") // This installs requestly chrome extension in your testing instance
  );

  const driver = new Builder()
    .forBrowser("chrome")
    .setChromeOptions(options)
    .build();

  await importRequestlySharedList(driver, sharedListUrl); // Here we import the shared list we created some time back
  driver.get("http://www.google.com/");
}

这是对我们如何克服纯硒方法缺点的高级概述。我已经写了一篇关于如何创建规则、共享列表等的博客。你可以阅读here.

TridentTrue 回答的启发,这里是 Selenium 4.0.0 在 C# 中的更新版本。如果有人知道如何将它用于 alpha7 及更高版本而没有特定版本,请随时更新。 :)

public void LimitNetwork(int latencyInMilliseconds, long downloadLimitMbps, long uploadLimitMbps)
{
    IDevTools devTools = driver as IDevTools;
    session = devTools.CreateDevToolsSession();
    session.Network.Enable(new EnableCommandSettings());

    EmulateNetworkConditionsCommandSettings command = new EmulateNetworkConditionsCommandSettings();

    command.Latency = latencyInMilliseconds;
    command.DownloadThroughput = downloadLimitMbps * 125000; // Mbps to bytes per second
    command.UploadThroughput = uploadLimitMbps * 125000; // Mbps to bytes per second
    command.Offline = false;

    session.Network.EmulateNetworkConditions(command);
}

更新:在我自己实现这个之后,我找到了一篇非常好的文章来获得 overview in Selenium 4.0,也在模拟网络条件中。

更新 2:我的问题是我忘记添加 Network.Enable 命令,所以不要忘记在执行其他操作之前调用它。 我已经更新了代码。 :)