设置自己的测试自动化环境

在本文中,我们将教你如何安装自己的自动化环境,并使用 Selenium/WebDriver 和测试库(如 Node 的 selenium-webdriver)运行自己的测试。我们还将探讨如何将本地测试环境与前一篇文章中讨论的商业工具集成。

先决条件 熟悉核心 HTMLCSSJavaScript 语言;了解 跨浏览器测试原则自动化测试 的高级概念。
目标 演示如何在本地设置 Selenium 测试环境并使用它运行测试,以及如何将其与 LambdaTest、Sauce Labs 和 BrowserStack 等工具集成。

Selenium

Selenium 是最流行的浏览器自动化工具。还有其他方法,但使用 Selenium 的最佳方法是通过 WebDriver,这是一个功能强大的 API,它建立在 Selenium 之上,并向浏览器发出调用以对其进行自动化,执行诸如“打开此网页”,“将鼠标悬停在此页面上的元素上”,“点击此链接”,“查看此链接是否打开此 URL”等操作。这非常适合运行自动化测试。

WebDriver 的安装和使用方式取决于你想使用什么编程环境来编写和运行测试。大多数流行的环境都提供一个包或框架,可以安装 WebDriver 和与 WebDriver 通信所需的绑定,例如 Java、C#、Ruby、Python、JavaScript(Node)等。有关不同语言的 Selenium 设置的更多详细信息,请参阅 设置 Selenium-WebDriver 项目

不同的浏览器需要不同的驱动程序才能让 WebDriver 与它们通信并控制它们。有关从哪里获取浏览器驱动程序的更多信息,请参阅 Selenium 支持的平台

我们将介绍如何使用 Node.js 编写和运行 Selenium 测试,因为它快速易于上手,并且对于前端开发人员来说是一个更熟悉的环境。

注意:如果你想了解如何在其他服务器端环境中使用 WebDriver,请查看 Selenium 支持的平台,其中包含一些有用的链接。

在 Node 中设置 Selenium

  1. 首先,设置一个新的 npm 项目,如上一章 设置 Node 和 npm 中所述。将其命名为不同的名称,例如 selenium-test
  2. 接下来,我们需要安装一个框架,以便我们可以在 Node 内部使用 Selenium。我们将选择 Selenium 官方的 selenium-webdriver,因为它的文档看起来相当最新且维护良好。如果你想要其他选择,webdriver.ionightwatch.js 也是不错的选择。要安装 selenium-webdriver,请运行以下命令,确保你位于项目文件夹中
    bash
    npm install selenium-webdriver
    

注意:即使你之前安装了 selenium-webdriver 并下载了浏览器驱动程序,也建议你按照这些步骤操作。你应该确保一切都已更新。

接下来,你需要下载相关的驱动程序,以使 WebDriver 能够控制你想要测试的浏览器。你可以在 selenium-webdriver 页面上(参见第一部分的表格)找到有关从哪里获取它们的详细信息。显然,有些浏览器是特定于操作系统的,但我们将坚持使用 Firefox 和 Chrome,因为它们在所有主要操作系统上都可用。

  1. 下载最新的 GeckoDriver(适用于 Firefox)和 ChromeDriver 驱动程序。
  2. 将它们解压到某个易于导航的地方,例如主用户目录的根目录。
  3. chromedrivergeckodriver 驱动程序的位置添加到系统 PATH 变量中。这应该从硬盘根目录到包含驱动程序的目录的绝对路径。例如,如果我们使用的是 macOS 机器,我们的用户名是 bob,并将驱动程序放在主文件夹的根目录中,则路径为 /Users/bob

注意:再说一遍,添加到 PATH 的路径需要是包含驱动程序的目录的路径,而不是驱动程序本身的路径!这是一个常见的错误。

要在 macOS 系统和大多数 Linux 系统上设置 PATH 变量

  1. 如果你还没有使用 bash shell(例如,在 macOS 系统上,默认 shell 是 zsh,而不是 bash),请切换到 bash shell
    bash
    exec bash
    
  2. 打开你的 .bash_profile(或 .bashrc)文件(如果你看不到隐藏文件,则需要显示它们,请参阅 在 macOS 中显示/隐藏隐藏文件在 Ubuntu 中显示隐藏文件夹)。
  3. 将以下内容粘贴到文件的底部(更新路径,使其与你的机器上的实际路径一致)
    bash
    #Add WebDriver browser drivers to PATH
    
    export PATH=$PATH:/Users/bob
    
  4. 保存并关闭此文件,然后重新启动你的终端/命令提示符以重新应用 Bash 配置。
  5. 通过在终端中输入以下内容来检查你的新路径是否在 PATH 变量中
    bash
    echo $PATH
    
  6. 你应该在终端中看到它被打印出来。

要在 Windows 上设置 PATH 变量,请按照 如何将新文件夹添加到系统路径? 中的说明操作。

好了,让我们尝试一个快速测试以确保一切正常。

  1. 在项目目录中创建一个名为 google_test.js 的新文件
  2. 将其内容设置为以下内容,然后保存它
    js
    const { Builder, Browser, By, Key, until } = require("selenium-webdriver");
    
    (async function example() {
      const driver = await new Builder().forBrowser(Browser.FIREFOX).build();
      try {
        await driver.get("https://www.google.com/ncr");
        await driver.findElement(By.name("q")).sendKeys("webdriver", Key.RETURN);
        await driver.wait(until.titleIs("webdriver - Google Search"), 1000);
      } finally {
        await driver.sleep(2000); // Delay long enough to see search page!
        await driver.quit();
      }
    })();
    

    注意:此函数是 IIFE(立即调用的函数表达式)。

  3. 在终端中,确保你位于项目文件夹中,然后输入以下命令
    bash
    node google_test
    

你应该会看到一个 Firefox 实例自动打开!Google 应该自动加载在一个选项卡中,“webdriver” 应该在搜索框中输入,并且搜索按钮将被点击。WebDriver 然后将等待 1 秒;然后访问文档标题,如果它是“webdriver - Google 搜索”,我们将返回一条消息,声称测试通过。然后我们等待 4 秒,之后 WebDriver 将关闭 Firefox 实例并停止。

在多个浏览器中同时进行测试

你也可以同时在多个浏览器上运行测试。让我们试试这个!

  1. 在项目目录中创建另一个名为 google_test_multiple.js 的新文件。你可以随意更改对我们添加的其他浏览器的引用,删除它们,等等,具体取决于你可以在你的操作系统上测试的浏览器。你需要确保你的系统上已设置了正确的浏览器驱动程序。关于在 .forBrowser() 方法中使用什么字符串来表示其他浏览器,请参阅 Browser 枚举 参考页面。
  2. 将其内容设置为以下内容,然后保存它
    js
    const { Builder, Browser, By, Key } = require("selenium-webdriver");
    
    const driver_fx = new Builder().forBrowser(Browser.FIREFOX).build();
    
    const driver_chr = new Builder().forBrowser(Browser.CHROME).build();
    
    async function searchTest(driver) {
      try {
        await driver.get("http://www.google.com");
        await driver.findElement(By.name("q")).sendKeys("webdriver", Key.RETURN);
        await driver.sleep(2000).then(async () => {
          await driver.getTitle().then(async (title) => {
            if (title === "webdriver - Google Search") {
              console.log("Test passed");
            } else {
              console.log("Test failed");
            }
          });
        });
      } finally {
        driver.quit();
      }
    }
    
    searchTest(driver_fx);
    searchTest(driver_chr);
    
  3. 在终端中,确保你位于项目文件夹中,然后输入以下命令
    bash
    node google_test_multiple
    
  4. 如果你使用的是 Mac 并决定测试 Safari,你可能会收到类似于“无法创建会话:你必须在 Safari 的“开发”菜单中启用“允许远程自动化”选项才能通过 WebDriver 控制 Safari”的错误消息。如果你遇到这种情况,请按照给定的说明操作,然后重试。

所以在这里,我们之前已经完成了测试,只是这次我们把它包装在一个函数 searchTest() 中。我们为多个浏览器创建了新的浏览器实例,然后将每个实例传递给函数,以便在所有三个浏览器上执行测试!

有趣吧?让我们继续,更详细地看一下 WebDriver 语法的基本知识。

WebDriver 语法速成课程

让我们看一下 WebDriver 语法的一些关键功能。有关更完整的详细信息,你应该咨询 selenium-webdriver JavaScript API 参考 以获取详细的参考以及 Selenium 主文档的 Selenium WebDriver,其中包含以多种语言编写的多个示例供你学习。

开始一个新的测试

要启动一个新的测试,你需要包含 selenium-webdriver 模块,导入 Builder 构造函数和 Browser 接口

js
const { Builder, Browser } = require("selenium-webdriver");

你使用 Builder() 构造函数来创建一个新的驱动程序实例,将 forBrowser() 方法链接起来以指定你想要使用此构建器测试的浏览器。build() 方法链接到末尾以实际构建驱动程序实例(有关这些功能的详细信息,请参阅 Builder 类参考)。

js
let driver = new Builder().forBrowser(Browser.FIREFOX).build();

请注意,可以为要测试的浏览器设置特定的配置选项,例如,你可以在 forBrowser() 方法中设置要测试的特定版本和操作系统

js
let driver = new Builder().forBrowser(Browser.FIREFOX, "46", "MAC").build();

你也可以使用环境变量设置这些选项,例如

bash
SELENIUM_BROWSER=firefox:46:MAC

让我们创建一个新的测试,以便在讨论它时探索此代码。在你的 Selenium 测试项目目录中,创建一个名为 quick_test.js 的新文件,并将以下代码添加到其中

js
const { Builder, Browser } = require("selenium-webdriver");

(async function example() {
  const driver = await new Builder().forBrowser(Browser.FIREFOX).build();
})();

获取你想要测试的文档

要加载你实际要测试的页面,可以使用你之前创建的驱动程序实例的 get() 方法,例如

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

注意:有关本节和它下面的功能的详细信息,请参阅 WebDriver 类参考

你可以使用任何 URL 来指向你的资源,包括 file:// URL 来测试本地文档

js
driver.get(
  "file:///Users/chrismills/git/learning-area/tools-testing/cross-browser-testing/accessibility/fake-div-buttons.html",
);

或者

js
driver.get("https://127.0.0.1:8888/fake-div-buttons.html");

但是,最好使用远程服务器位置,这样代码更加灵活——当你开始使用远程服务器运行测试时(见后文),如果你尝试使用本地路径,你的代码将无法运行。

更新你的 example() 函数,如下所示

js
const { Builder, Browser } = require("selenium-webdriver");

(async function example() {
  const driver = await new Builder().forBrowser(Browser.FIREFOX).build();
  driver.get(
    "https://mdn.github.io/learning-area/tools-testing/cross-browser-testing/accessibility/native-keyboard-accessibility.html",
  );
})();

与文档交互

现在我们有了要测试的文档,我们需要以某种方式与它交互,这通常涉及首先选择一个特定的元素来测试有关它的内容。你可以在 WebDriver 中 以多种方式选择 UI 元素,包括按 ID、类、元素名称等。实际选择由 findElement() 方法完成,它接受一个选择方法作为参数。例如,要按 ID 选择一个元素

js
const element = driver.findElement(By.id("myElementId"));

使用 CSS 查找元素的最有用方法之一是 By.css() 方法,它允许你使用 CSS 选择器选择元素。

现在更新你的 example() 函数,如下所示

js
const { Builder, Browser, By } = require("selenium-webdriver");

(async function example() {
  const driver = await new Builder().forBrowser(Browser.FIREFOX).build();
  driver.get(
    "https://mdn.github.io/learning-area/tools-testing/cross-browser-testing/accessibility/native-keyboard-accessibility.html",
  );
  const button = driver.findElement(By.css("button:nth-of-type(1)"));
})();

测试你的元素

有许多方法可以与 Web 文档及其上的元素交互。你可以从 WebDriver 文档的 获取文本值 开始,查看一些有用的常见示例。

如果我们想要获取按钮内部的文本,我们可以这样做

js
button.getText().then((text) => {
  console.log(`Button text is '${text}'`);
});

现在将此添加到 example() 函数的底部,如下所示

js
const { Builder, Browser, By } = require("selenium-webdriver");

(async function example() {
  const driver = await new Builder().forBrowser(Browser.FIREFOX).build();

  driver.get(
    "https://mdn.github.io/learning-area/tools-testing/cross-browser-testing/accessibility/native-keyboard-accessibility.html",
  );

  const button = driver.findElement(By.css("button:nth-of-type(1)"));

  button.getText().then((text) => {
    console.log(`Button text is '${text}'`);
  });
})();

确保你位于项目目录中,尝试运行测试

bash
node quick_test.js

你应该在控制台中看到按钮的文本标签被报告出来。

让我们做一些更有用的事情。将前面的代码条目替换为以下代码行 button.click();,如下所示

js
const { Builder, Browser, By } = require("selenium-webdriver");

(async function example() {
  const driver = await new Builder().forBrowser(Browser.FIREFOX).build();
  driver.get(
    "https://mdn.github.io/learning-area/tools-testing/cross-browser-testing/accessibility/native-keyboard-accessibility.html",
  );

  const button = driver.findElement(By.css("button:nth-of-type(1)"));

  button.click();
})();

尝试再次运行你的测试;按钮将被点击,并且 alert() 弹出窗口将出现。至少我们知道按钮是有效的!

你也可以与弹出窗口交互。更新 example() 函数,如下所示,然后尝试再次测试它

js
const { Builder, Browser, By, until } = require("selenium-webdriver");

(async function example() {
  const driver = await new Builder().forBrowser(Browser.FIREFOX).build();

  driver.get(
    "https://mdn.github.io/learning-area/tools-testing/cross-browser-testing/accessibility/native-keyboard-accessibility.html",
  );

  const button = driver.findElement(By.css("button:nth-of-type(1)"));

  button.click();

  await driver.wait(until.alertIsPresent());

  const alert = driver.switchTo().alert();

  alert.getText().then((text) => {
    console.log(`Alert text is '${text}'`);
  });

  alert.accept();
})();

接下来,让我们尝试将一些文本输入到表单元素中。更新example()函数如下,然后尝试再次运行您的测试

js
const { Builder, Browser, By, until } = require("selenium-webdriver");

(async function example() {
  const driver = await new Builder().forBrowser(Browser.FIREFOX).build();
  driver.get(
    "https://mdn.github.io/learning-area/tools-testing/cross-browser-testing/accessibility/native-keyboard-accessibility.html",
  );

  const input = driver.findElement(By.id("name"));
  input.sendKeys("Filling in my form");

  const button = driver.findElement(By.css("button:nth-of-type(1)"));

  button.click();
  await driver.wait(until.alertIsPresent());

  const alert = driver.switchTo().alert();

  alert.getText().then((text) => {
    console.log(`Alert text is '${text}'`);
  });

  alert.accept();
})();

您可以使用Key对象的属性提交无法用普通字符表示的按键。例如,在上面我们使用此构造在提交表单输入之前跳出表单输入

js
driver.sleep(1000).then(() => {
  driver.findElement(By.name("q")).sendKeys(Key.TAB);
});

等待某些操作完成

有时您希望让 WebDriver 等待某些操作完成,然后再继续执行。例如,如果您加载新页面,您可能希望等待页面的 DOM 加载完毕,然后再尝试与任何元素进行交互,否则测试很可能会失败。

例如,在我们的google_test.js测试中,我们包含了此代码块

js
driver.sleep(2000).then(() => {
  driver.getTitle().then((title) => {
    if (title === "webdriver - Google Search") {
      console.log("Test passed");
    } else {
      console.log("Test failed");
    }
  });
});

sleep()方法接受一个值,该值指定以毫秒为单位的等待时间 - 该方法返回一个在该时间结束时解析的承诺,此时then()内部的代码将执行。在这种情况下,我们使用getTitle()方法获取当前页面的标题,然后根据其值返回通过或失败消息。

我们也可以在quick_test.js测试中添加sleep()方法 - 尝试像这样更新您的example()函数

js
const { Builder, Browser, By, until } = require("selenium-webdriver");

const driver = new Builder().forBrowser("firefox").build();

(async function example() {
  try {
    driver.get(
      "https://mdn.github.io/learning-area/tools-testing/cross-browser-testing/accessibility/native-keyboard-accessibility.html",
    );

    driver.sleep(2000).then(() => {
      const input = driver.findElement(By.id("name"));

      input.sendKeys("Filling in my form");
      input.getAttribute("value").then((value) => {
        if (value !== "") {
          console.log("Form input editable");
        }
      });
    });

    const button = driver.findElement(By.css("button:nth-of-type(1)"));

    button.click();

    await driver.wait(until.alertIsPresent());

    const alert = driver.switchTo().alert();

    alert.getText().then((text) => {
      console.log(`Alert text is '${text}'`);
    });

    alert.accept();
  } finally {
    await driver.sleep(4000); // Delay long enough to see search page!
    driver.quit();
  }
})();

WebDriver 现在将等待 2 秒,然后再填写表单字段。然后我们通过使用getAttribute()检索其value属性值来测试其值是否已填充(即不为空),如果其不为空,则向控制台打印一条消息。

注意:还有一种名为wait()的方法,它会在一定时间内反复测试条件,然后继续执行代码。这也利用了util 库,它定义了与wait()一起使用的常见条件。

使用后关闭驱动程序

完成测试运行后,您应该关闭打开的所有驱动程序实例,以确保您的机器上不会出现大量未关闭的浏览器实例!这可以使用quit()方法完成。在您完成对驱动程序实例的操作后,在您的驱动程序实例上调用此方法。现在将此行添加到quick_test.js测试的底部

js
driver.quit();

运行它时,您现在应该看到测试执行,并且浏览器实例在测试完成后再次关闭。这对于避免用大量浏览器实例弄乱您的计算机非常有用,尤其是当您拥有的浏览器实例过多以至于导致计算机变慢时。

测试最佳实践

已经有很多关于编写测试最佳实践的文章。您可以在测试实践中找到一些有用的背景信息。一般来说,您应该确保您的测试是

  1. 使用良好的定位策略:当您与文档交互时,请确保您使用的定位器和页面对象不太可能发生更改 - 如果您有一个可测试的元素要对其执行测试,请确保它具有稳定的 ID,或者可以使用 CSS 选择器选择的页面位置,该位置不会在下一次网站迭代中发生更改。您希望使您的测试尽可能地不脆弱,即它们不会在发生更改时轻易崩溃。
  2. 编写原子测试:每个测试都应该只测试一项内容,这样可以轻松地跟踪哪个测试文件测试了哪个标准。例如,我们上面看到的google_test.js测试非常好,因为它只测试了一件事 - 搜索结果页面的标题是否设置正确。我们可以努力为它起一个更好的名字,这样如果我们添加更多 Google 测试,就可以更容易地确定它做了什么。也许results_page_title_set_correctly.js会稍微好一些?
  3. 编写自主测试:每个测试都应该独立运行,而不依赖于其他测试才能运行。

此外,我们应该提一下测试结果/报告 - 我们一直在使用简单的console.log()语句在我们上面的示例中报告结果,但这完全是在 JavaScript 中完成的,因此您可以使用任何您想要的测试运行和报告系统,无论是MochaChai还是其他工具。

  1. 例如,尝试在您的项目目录中制作我们mocha_test.js示例的本地副本。将其放在名为test的子文件夹中。此示例使用长长的承诺链来运行测试中所需的所有步骤 - WebDriver 使用的基于承诺的方法需要解析才能正常工作。
  2. 通过在您的项目目录中运行以下命令来安装 mocha 测试工具
    bash
    npm install --save-dev mocha
    
  3. 您现在可以使用以下命令运行测试(以及您放在test目录中的任何其他测试)
    bash
    npx mocha --no-timeouts
    
  4. 您应该包含--no-timeouts标志,以确保您的测试不会由于 Mocha 的任意超时(为 3 秒)而最终失败。

注意:saucelabs-sample-test-frameworks包含多个有用的示例,展示了如何设置测试/断言工具的不同组合。

运行远程测试

事实证明,在远程服务器上运行测试与在本地运行测试并没有那么难。您只需要创建驱动程序实例,但需要指定更多功能,包括要测试的浏览器的功能、服务器的地址以及您访问它所需的(如果有)用户凭据。

LambdaTest

让 Selenium 测试在 LambdaTest 上远程运行非常简单。您需要的代码应该遵循下面看到的模式。

让我们编写一个示例

  1. 在您的项目目录中,创建一个名为lambdatest_google_test.js的新文件
  2. 赋予它以下内容
    js
    const { By, Builder } = require("selenium-webdriver");
    
    // username: Username can be found at automation dashboard
    const USERNAME = "{username}";
    
    // AccessKey: AccessKey can be generated from automation dashboard or profile section
    const KEY = "{accessKey}";
    
    // gridUrl: gridUrl can be found at automation dashboard
    const GRID_HOST = "hub.lambdatest.com/wd/hub";
    
    function searchTextOnGoogle() {
      // Setup Input capabilities
      const capabilities = {
        platform: "windows 10",
        browserName: "chrome",
        version: "67.0",
        resolution: "1280x800",
        network: true,
        visual: true,
        console: true,
        video: true,
        name: "Test 1", // name of the test
        build: "NodeJS build", // name of the build
      };
    
      // URL: https://{username}:{accessToken}@hub.lambdatest.com/wd/hub
      const gridUrl = `https://${USERNAME}:${KEY}@${GRID_HOST}`;
    
      // setup and build selenium driver object
      const driver = new Builder()
        .usingServer(gridUrl)
        .withCapabilities(capabilities)
        .build();
    
      // navigate to a URL, search for a text and get title of page
      driver.get("https://www.google.com/ncr").then(function () {
        driver
          .findElement(By.name("q"))
          .sendKeys("LambdaTest\n")
          .then(function () {
            driver.getTitle().then((title) => {
              setTimeout(() => {
                if (title === "LambdaTest - Google Search") {
                  driver.executeScript("lambda-status=passed");
                } else {
                  driver.executeScript("lambda-status=failed");
                }
                driver.quit();
              }, 5000);
            });
          });
      });
    }
    
    searchTextOnGoogle();
    
  3. 访问您的LambdaTest 自动化仪表板,通过点击右上角的key图标(参见用户名和访问密钥)来获取您的 LambdaTest 的用户名和访问密钥。用您的实际用户名和访问密钥值替换代码中的{username}{accessKey}占位符(并确保您将它们保密)。
  4. 在您的终端中运行以下命令来执行您的测试
    bash
    node lambdatest_google_test
    
    测试将被发送到 LambdaTest,并且您的测试输出将在您的 LambdaTest 控制台中反映出来。如果您希望从 LambdaTest 平台提取这些结果以用于报告目的,那么您可以通过使用LambdaTest restful API来实现。
  5. 现在,如果您转到您的LambdaTest 自动化仪表板,您将看到您的测试列出;从这里,您将能够看到视频、屏幕截图和其他此类数据。您还将看到通过失败而不是完成的状态,因为代码中有ifelse代码块。LambdaTest 自动化仪表板 您可以为每个测试版本中的每个测试检索网络、命令、异常和 Selenium 日志。您还将找到 Selenium 脚本执行的视频录制。

注意:LambdaTest 自动化仪表板上的帮助按钮将为您提供大量信息,帮助您开始使用 LambdaTest 自动化。您也可以关注我们关于在 Node JS 中运行第一个 Selenium 脚本的文档。

注意:如果您不想手动编写测试的功能对象,您可以使用Selenium Desired Capabilities Generator来生成它们。

BrowserStack

让 Selenium 测试在 BrowserStack 上远程运行很简单。您需要的代码应该遵循下面看到的模式。

让我们编写一个示例

  1. 在您的项目目录中,创建一个名为bstack_google_test.js的新文件。
  2. 赋予它以下内容
    js
    const { Builder, By, Key } = require("selenium-webdriver");
    const request = require("request");
    
    // Input capabilities
    const capabilities = {
      "bstack:options": {
        os: "OS X",
        osVersion: "Sonoma",
        browserVersion: "17.0",
        local: "false",
        seleniumVersion: "3.14.0",
        userName: "YOUR-USER-NAME",
        accessKey: "YOUR-ACCESS-KEY",
      },
      browserName: "Safari",
    };
    
    const driver = new Builder()
      .usingServer("http://hub-cloud.browserstack.com/wd/hub")
      .withCapabilities(capabilities)
      .build();
    
    (async function bStackGoogleTest() {
      try {
        await driver.get("https://www.google.com/");
        await driver.findElement(By.name("q")).sendKeys("webdriver", Key.RETURN);
        await driver.sleep(2000);
        const title = await driver.getTitle();
        if (title === "webdriver - Google Search") {
          console.log("Test passed");
        } else {
          console.log("Test failed");
        }
      } finally {
        await driver.sleep(4000); // Delay long enough to see search page!
        await driver.quit();
      }
    })();
    
  3. 从您的BrowserStack 帐户 - 摘要中获取您的用户名和访问密钥(参见用户名和访问密钥)。用您的实际用户名和访问密钥值替换代码中的YOUR-USER-NAMEYOUR-ACCESS-KEY占位符(并确保您将它们保密)。
  4. 使用以下命令运行您的测试
    bash
    node bstack_google_test
    
    测试将被发送到 BrowserStack,测试结果将返回到您的控制台中。这表明包含某种结果报告机制的重要性!
  5. 现在,如果您返回到BrowserStack 自动化仪表板页面,您将看到您的测试列出:BrowserStack 自动化结果

如果您单击测试的链接,您将进入一个新屏幕,在那里您将能够看到测试的视频录制以及多个与之相关的详细信息日志。

注意:Browserstack 自动化仪表板上的资源菜单选项包含大量关于如何使用它运行自动化测试的有用信息。有关 Node JS 特定信息,请参见在 Node JS 中编写自动化测试脚本的 Node JS 文档。探索文档以找出 BrowserStack 可以执行的所有有用操作。

注意:如果您不想手动编写测试的功能对象,您可以使用文档中嵌入的生成器来生成它们。请参见运行您的第一个测试

以编程方式填写 BrowserStack 测试详细信息

您可以使用 BrowserStack REST API 和其他一些功能来为您的测试添加更多详细信息,例如它是否通过、为什么通过、测试属于哪个项目等等。BrowserStack 默认情况下不知道这些详细信息!

让我们更新我们的bstack_google_test.js演示,以展示这些功能如何工作

  1. 通过在您的项目目录中运行以下命令来安装 request 模块
    js
    npm install request
    
  2. 然后,我们需要导入节点 request 模块,以便我们可以使用它来向 REST API 发送请求。在代码的最上面添加以下行
    js
    const request = require("request");
    
  3. 现在我们将更新我们的capabilities对象以包含项目名称 - 在关闭的花括号之前添加以下行,记住在上一行的末尾添加逗号(您可以更改构建和项目名称以在 BrowserStack 自动化仪表板中的不同窗口中组织测试)
    js
    'project' : 'Google test 2'
    
  4. 接下来,我们需要访问当前会话的sessionId,以便我们知道将请求发送到哪里(该 ID 包含在请求 URL 中,您将在后面看到)。将以下几行添加到创建driver对象的代码块(let driver …)下方。
    js
    let sessionId;
    
    driver.session_.then((sessionData) => {
      sessionId = sessionData.id_;
    });
    
  5. 最后,更新代码底部附近的driver.sleep(2000)代码块以添加 REST API 调用(同样,请将代码中的YOUR-USER-NAMEYOUR-ACCESS-KEY占位符替换为您的实际用户名和访问密钥值)。
    js
    driver.sleep(2000).then(() => {
      driver.getTitle().then((title) => {
        if (title === "webdriver - Google Search") {
          console.log("Test passed");
          request({
            uri: `https://YOUR-USER-NAME:[email protected]/automate/sessions/${sessionId}.json`,
            method: "PUT",
            form: {
              status: "passed",
              reason: "Google results showed correct title",
            },
          });
        } else {
          console.log("Test failed");
          request({
            uri: `https://YOUR-USER-NAME:[email protected]/automate/sessions/${sessionId}.json`,
            method: "PUT",
            form: {
              status: "failed",
              reason: "Google results showed wrong title",
            },
          });
        }
      });
    });
    

这些代码非常直观——测试完成后,我们会向 BrowserStack 发送 API 调用,以更新测试状态为通过或失败,以及结果原因。

现在,如果您返回到BrowserStack 自动化仪表板页面,您应该会看到您的测试会话可用,如之前一样,但附加了更新的数据。

BrowserStack Custom Results

Sauce Labs

让 Selenium 测试在 Sauce Labs 上远程运行也非常简单,并且与 BrowserStack 非常类似,只是语法略有不同。您需要的代码应遵循以下模式。

让我们编写一个示例

  1. 在您的项目目录中,创建一个名为sauce_google_test.js的新文件。
  2. 赋予它以下内容
    js
    const { Builder, By, Key } = require("selenium-webdriver");
    const username = "YOUR-USER-NAME";
    const accessKey = "YOUR-ACCESS-KEY";
    
    const driver = new Builder()
      .withCapabilities({
        browserName: "chrome",
        platform: "Windows XP",
        version: "43.0",
        username,
        accessKey,
      })
      .usingServer(
        `https://${username}:${accessKey}@ondemand.saucelabs.com:443/wd/hub`,
      )
      .build();
    
    driver.get("http://www.google.com");
    
    driver.findElement(By.name("q")).sendKeys("webdriver");
    
    driver.sleep(1000).then(() => {
      driver.findElement(By.name("q")).sendKeys(Key.TAB);
    });
    
    driver.findElement(By.name("btnK")).click();
    
    driver.sleep(2000).then(() => {
      driver.getTitle().then((title) => {
        if (title === "webdriver - Google Search") {
          console.log("Test passed");
        } else {
          console.log("Test failed");
        }
      });
    });
    
    driver.quit();
    
  3. 从您的Sauce Labs 用户设置中获取您的用户名和访问密钥。将代码中的YOUR-USER-NAMEYOUR-ACCESS-KEY占位符替换为您的实际用户名和访问密钥值(并确保您将其保密)。
  4. 使用以下命令运行您的测试
    bash
    node sauce_google_test
    
    测试将被发送到 Sauce Labs,测试结果将返回到您的控制台。这表明包含某种结果报告机制的重要性!
  5. 现在,如果您转到Sauce Labs 自动测试仪表板页面,您将看到您的测试列表;从这里,您将能够看到视频、屏幕截图和其他此类数据。Sauce Labs 自动测试

注意: Sauce Labs 的平台配置器是一个有用的工具,用于生成要提供给您的驱动程序实例的功能对象,这些对象基于您想要测试的浏览器/操作系统。

注意:有关使用 Sauce Labs 和 Selenium 进行测试的更多有用详细信息,请查看Selenium 自动网站测试入门即时 Selenium Node.js 测试

以编程方式填写 Sauce Labs 测试详细信息

您可以使用 Sauce Labs API 用更多详细信息注释您的测试,例如它是否通过、测试名称等。默认情况下,Sauce Labs 不会知道这些详细信息!

为此,您需要

  1. 使用以下命令安装 Node Sauce Labs 包装器(如果您尚未为该项目完成此操作)
    bash
    npm install saucelabs --save-dev
    
  2. 需要 saucelabs——将此放在sauce_google_test.js文件的顶部,位于之前的变量声明下方
    js
    const SauceLabs = require("saucelabs");
    
  3. 创建一个新的 SauceLabs 实例,方法是在其下方添加以下内容
    js
    const saucelabs = new SauceLabs({
      username: "YOUR-USER-NAME",
      password: "YOUR-ACCESS-KEY",
    });
    
    同样,将代码中的YOUR-USER-NAMEYOUR-ACCESS-KEY占位符替换为您的实际用户名和访问密钥值(请注意,saucelabs npm 包比较令人困惑地使用password而不是accessKey)。由于您现在已经使用了两次,因此您可能希望创建几个辅助变量来存储它们。
  4. 在定义driver变量的代码块下方(紧随build()行之后),添加以下代码块——这将获取我们需要写入作业的正确驱动程序sessionID(您可以在下一个代码块中看到它在起作用)
    js
    driver.getSession().then((sessionid) => {
      driver.sessionID = sessionid.id_;
    });
    
  5. 最后,用以下内容替换代码底部附近的driver.sleep(2000)代码块
    js
    driver.sleep(2000).then(() => {
      driver.getTitle().then((title) => {
        let testPassed = false;
        if (title === "webdriver - Google Search") {
          console.log("Test passed");
          testPassed = true;
        } else {
          console.error("Test failed");
        }
    
        saucelabs.updateJob(driver.sessionID, {
          name: "Google search results page title test",
          passed: testPassed,
        });
      });
    });
    

在这里,我们设置了一个testPassed变量,根据测试是通过还是失败,将其设置为truefalse,然后我们使用saucelabs.updateJob()方法更新详细信息。

现在,如果您返回到Sauce Labs 自动测试仪表板页面,您应该会看到您的新作业现在附加了更新的数据。

Sauce Labs Updated Job info

您自己的远程服务器

如果您不想使用 Sauce Labs 或 BrowserStack 等服务,您可以随时设置自己的远程测试服务器。让我们看看如何做到这一点。

  1. Selenium 远程服务器需要 Java 才能运行。从Java SE 下载页面下载适用于您平台的最新 JDK。下载完成后进行安装。
  2. 接下来,下载最新的Selenium 独立服务器——它充当您的脚本和浏览器驱动程序之间的代理。选择最新的稳定版本号(即不是 beta 版),然后从列表中选择以“selenium-server-standalone”开头的文件。下载完成后,将其放在一个合适的位置,例如您的主目录中。如果您尚未将该位置添加到您的PATH中,请立即添加(请参阅在 Node 中设置 Selenium部分)。
  3. 通过在服务器计算机上的终端中输入以下内容来运行独立服务器
    bash
    java -jar selenium-server-standalone-3.0.0.jar
    
    (更新.jar文件名)使其与您拥有的文件完全匹配。
  4. 服务器将在https://127.0.0.1:4444/wd/hub上运行——现在尝试访问该地址,看看会发生什么。

现在,服务器已经运行,让我们创建一个将在远程 Selenium 服务器上运行的演示测试。

  1. 复制您的google_test.js文件,并将其命名为google_test_remote.js;将其放在您的项目目录中。
  2. 更新代码行(以const driver = …开头)如下
    js
    const driver = new Builder()
      .forBrowser(Browser.FIREFOX)
      .usingServer("https://127.0.0.1:4444/wd/hub")
      .build();
    
  3. 运行您的测试,您应该会看到它按预期运行;但是这次,您将在独立服务器上运行它。
    bash
    node google_test_remote.js
    

所以这很酷。我们已经在本地测试过它,但您可以将其设置在几乎任何服务器上,以及相关的浏览器驱动程序,然后使用您选择公开的 URL 连接您的脚本。

将 Selenium 与 CI 工具集成

另外一点是,还可以将 Selenium 和 LambdaTest、Sauce Labs 等相关工具与持续集成 (CI) 工具集成——这很有用,因为这意味着您可以通过 CI 工具运行测试,并且只有在测试通过时才将新更改提交到您的代码存储库。

在本文中详细介绍这个领域不在我们的范围之内,但我们建议您从 Travis CI 开始——这可能是最容易上手的 CI 工具,并且与 GitHub 和 Node 等 Web 工具有很好的集成。

要开始使用,请参阅例如

注意:如果您希望使用无代码自动化执行持续测试,那么您可以使用EndtestTestingBot

摘要

本模块应该很有趣,并且应该让您对编写和运行自动化测试有足够的了解,以便您可以开始编写自己的自动化测试。