codecamp

Setting up your own test automation environment

先决条件: 熟悉核心 HTML CSS JavaScript 语言; 高级跨浏览器测试原则自动测试的概念。
目的: 展示如何在本地设置Selenium测试环境并使用它运行测试,以及如何将它与诸如Sauce Labs之类的应用程序集成。

Selenium 是最流行的浏览器自动化工具。 还有其他方法,但使用Selenium的最好方法是通过WebDriver,一个强大的API,建立在Selenium之上,并调用浏览器自动化,执行诸如"打开此网页","移动 页面上的此元素","单击此链接","查看链接是否打开此URL"等。这是运行自动测试的理想选择。

如何安装和使用WebDriver取决于您想要用来编写和运行测试的编程环境。 最流行的环境提供了一个包或框架,它将安装WebDriver和使用这种语言与WebDriver通信所需的绑定,例如Java,C#,Ruby,Python,JavaScript(Node)等。参见 href ="http://www.seleniumhq.org/docs/03_webdriver.jsp#setting-up-a-selenium-webdriver-project">设置Selenium-WebDriver项目了解有关Selenium设置的更多详细信息 不同的语言。

不同的浏览器需要不同的驱动程序,以允许WebDriver与其通信和控制它们。 有关从何处获取浏览器驱动程序的详细信息,请参阅 Selenium支持的平台等。

我们将介绍使用Node.js编写和运行Selenium测试,因为它快速而容易上手,并为前端开发人员提供了一个更熟悉的环境。

注意:如果您想了解如何在其他服务器端环境中使用WebDriver,请查看 /platforms.jsp">由Selenium支持的平台一些有用的链接。

在Node中设置Selenium

  1. To start with, set up a new npm project, as discussed in Setting up Node and npm in the last chapter. Call it something different, like selenium-test.
  2. Next, we need to install a framework to allow us to work with Selenium from inside Node. We are going to choose selenium's official selenium-webdriver, as the documentation seems fairly up-to-date, and it is well-maintained. If you want a different options, webdriver.io and nightwatch.js are also good options. To install selenium-webdriver, run the following command, making sure you are inside your project folder:
    npm install selenium-webdriver

注意:即使您之前安装了selenium-webdriver并下载了浏览器驱动程序,仍然遵循这些步骤仍然是个好主意。 你应该确保一切都是最新的。

接下来,您需要下载相关的驱动程序,以允许WebDriver控制您要测试的浏览器。 您可以在 selenium-webdriver 页面上查看从何处获取详细信息(请参阅 显然,一些浏览器是操作系统特定的,但我们将坚持使用Firefox和Chrome,因为它们可用于所有的主要操作系统。

  1. Download the latest GeckoDriver (for Firefox) and ChromeDriver drivers.
  2. Unpack them into somewhere fairly easy to navigate to, like the root of your home user directory.
  3. Add the chromedriver and geckodriver driver's location to your system PATH variable. This should be an absolute path from the root of your hard disk, to the directory containing the drivers. For example, if we were using a Mac OS X machine, our user name was bob, and we put our drivers in the root of our home folder, the path would be /Users/bob.

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

在Mac OS X /大多数Linux系统上设置 PATH 变量:

  1. Open your .bash_profile (or .bashrc) file (if you can't see hidden files, you'll need to display them, see Show/Hide hidden files in Mac OS X or Show hidden folders in Ubuntu).
  2. Paste the following into the bottom of your file (updating the path as it actually is on your machine):
    #Add WebDriver browser drivers to PATH
    
    export PATH=$PATH:/Users/bob
  3. Save and close this file, then restart your Terminal/command prompt to reapply your Bash configuration.
  4. Check that your new paths are in the PATH variable by entering the following into your terminal:
    echo $PATH
  5. You should see it printed out in the terminal.

要在Windows上设置 PATH 变量,请按照 -folder-my-system-path">如何将新文件夹添加到我的系统路径?

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

  1. Create a new file inside your project directory called google_test.js:
  2. Give it the following contents, then save it:
    var webdriver = require('selenium-webdriver'),
        By = webdriver.By,
        until = webdriver.until;
    
    var driver = new webdriver.Builder()
        .forBrowser('firefox')
        .build();
    
    driver.get('http://www.google.com');
    driver.findElement(By.name('q')).sendKeys('webdriver');
    driver.findElement(By.name('btnG')).click();
    
    driver.sleep(2000).then(function() {
      driver.getTitle().then(function(title) {
        if(title === 'webdriver - Google Search') {
          console.log('Test passed');
        } else {
          console.log('Test failed');
        }
      });
    });
    
    driver.quit();
  3. In terminal, make sure you are inside your project folder, then enter the following command:
    node google_test

您应该会看到Firefox的一个实例自动打开! Google应自动加载到标签中,应在搜索框中输入"webdriver",然后点击搜索按钮。 WebDriver会等待2秒; 然后访问文档标题,如果是"webdriver - Google搜索",我们将返回一条消息以声明测试通过。 WebDriver将关闭Firefox实例并停止。

一次在多个浏览器中测试

也没有什么可以阻止你在多个浏览器上同时运行测试。 让我们试试这个!

  1. Create another new file inside your project directory called google_test_multiple.js. You can feel free to change the references to some of the other browsers we added, remove them, etc., depending on what browsers you have available to test on your operating system. In terms of what string to use inside the .forBrowser() method for other browsers,  see the Browser enum reference page.
  2. Give it the following contents, then save it:
    var webdriver = require('selenium-webdriver'),
        By = webdriver.By,
        until = webdriver.until;
    
    var driver_fx = new webdriver.Builder()
        .forBrowser('firefox')
        .build();
    
    var driver_chr = new webdriver.Builder()
        .forBrowser('chrome')
        .build();
    
    var driver_saf = new webdriver.Builder()
        .forBrowser('safari')
        .build();
    
    searchTest(driver_fx);
    searchTest(driver_chr);
    searchTest(driver_saf);
    
    function searchTest(driver) {
      driver.get('http://www.google.com');
      driver.findElement(By.name('q')).sendKeys('webdriver');
      driver.findElement(By.name('btnG')).click();
    
      driver.sleep(2000).then(function() {
        driver.getTitle().then(function(title) {
          if(title === 'webdriver - Google Search') {
            console.log('Test passed');
          } else {
            console.log('Test failed');
          }
        });
      });
    
      driver.quit();
    }
  3. In terminal, make sure you are inside your project folder, then enter the following command:
    node google_test_multiple

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

有趣吗? 让我们继续,看一下WebDriver语法的基础知识,更详细一点。

WebDriver语法崩溃过程

让我们来看看webdriver语法的几个主要特性。 有关更完整的详细信息,请参阅 selenium-webdriver JavaScript API 参考以获取详细参考,以及Selenium主文档的 Selenium WebDriver 和 a class ="external"href ="http://www.seleniumhq.org/docs/04_webdriver_advanced.jsp"> WebDriver:Advanced Usage 页面,其中包含多个以不同语言编写的示例。

开始新测试

要启动新测试,您需要包含 selenium-webdriver 模块,如下所示:

var webdriver = require('selenium-webdriver'),
    By = webdriver.By,
    until = webdriver.until;

接下来,您需要使用 new webdriver.Builder()构造函数创建驱动程序的新实例。 这需要将 forBrowser()方法链接到它上,以指定要使用此构建器测试的浏览器以及 build()方法来实际构建它 详细信息,请参见 Builder类参考 对这些功能)。

var driver = new webdriver.Builder()
    .forBrowser('firefox')
    .build();

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

var driver = new webdriver.Builder()
    .forBrowser('firefox', '46', 'MAC')
    .build();

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

SELENIUM_BROWSER=firefox:46:MAC

让我们创建一个新的测试,让我们探讨这段代码,我们谈论它。 在selenium测试项目目录中,创建一个名为 quick_test.js 的新文件,并在其中添加以下代码:

var webdriver = require('selenium-webdriver'),
    By = webdriver.By,
    until = webdriver.until;

var driver = new webdriver.Builder()
    .forBrowser('firefox')
    .build();

获取要测试的文档

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

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

注意:请参阅 -webdriver / lib / webdriver_exports_WebDriver.html"> WebDriver类参考,了解本节中的功能及其下面的功能的详细信息。

您可以使用任何网址指向您的资源,包括用于测试本地文档的 file:// 网址:

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

要么

driver.get('http://localhost:8888/fake-div-buttons.html');

但是最好使用远程服务器位置,以便代码更灵活 - 当您开始使用远程服务器运行测试(见后文)时,如果您尝试使用本地路径,您的代码将会中断。

现在将此行添加到 quick_test.js 的底部:

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

与文档交互

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

var element = driver.findElement(By.id('myElementId'));

通过CSS查找元素的最有用的方法之一 - By.css方法允许您使用CSS选择器选择一个元素

现在在 quick_test.js 代码的底部输入以下内容:

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

测试您的元素

有很多方法可以与您的Web文档和元素进行交互。 您可以从获取文字值开始查看有用的常见示例 WebDriver文档。

如果我们想要在我们的按钮中获取文本,我们可以这样做:

button.getText().then(function(text) {
  console.log('Button text is \'' + text + '\'');
});

现在将它添加到 quick_test.js 中。

确保您在项目目录中,尝试运行测试:

node quick_test.js

您应该会在控制台中看到按钮的文字标签。

让我们做一些更有用的东西。 删除以前的代码条目,然后在底部添加此行代替:

button.click();

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

您可以与弹出窗口进行交互。 将以下代码添加到代码的底部,然后尝试重新测试:

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

alert.getText().then(function(text) {
  console.log('Alert text is \'' + text + '\'');
});

alert.accept();

接下来,让我们尝试在一个表单元素中输入一些文本。 添加以下代码,然后尝试再次运行测试:

var input = driver.findElement(By.id('input1'));
input.sendKeys('Filling in my form');

等待东西完成

有些时候,你想让WebDriver等待某事完成后再继续。 例如,如果加载新页面,您将需要等待页面的DOM完成加载,然后再尝试与其任何元素交互,否则测试可能会失败。

例如,在我们的 google_test.js 测试中,我们添加了此块:

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

sleep()方法接受一个值,该值指定以毫秒为单位的等待时间 - 该方法返回一个在该时间结束时解析的promise,此时 then )执行。 在这种情况下,我们使用 getTitle()方法获取当前页面的标题,然后根据它的值返回一个pass或fail消息。

我们可以在 quick_test.js 测试中添加 sleep()方法 - 尝试将最后一行代码包装在这样的块中:

driver.sleep(2000).then(function() {
  input.sendKeys('Filling in my form');
  input.getAttribute("value").then(function(value) {
    if(value !== '') {
      console.log('Form input editable');
    }
  });
});

WebDriver现在将等待2秒钟,然后填写表单字段。 然后,我们通过使用 getAttribute()来检索它的 value 属性值,然后测试它的值是否被填入(即不为空) 不是空的。

注意:还有一个名为 webdriver / lib / webdriver_exports_WebDriver.html#wait"> wait() ,它反复测试条件一段时间,然后继续执行代码。 这也使用 util library / a>,它定义了与 wait()一起使用的公共条件。

使用后关闭驱动程序

运行测试后,您应该关闭所有打开的dirver实例,以确保您不会在您的计算机上打开大量的流氓浏览器实例! 这是使用 quit()方法完成的。 只需在您的驱动程序实例上调用它,当您完成它。 现在将此行添加到 quick_test.js 测试的底部:

driver.quit();

当您运行它时,您现在应该看到测试执行和浏览器实例在文本完成后再次关闭。 这对于不使浏览器实例的负载混乱您的计算机很有用,尤其是如果你有这么多,导致计算机减速。

测试最佳做法

有很多关于写测试的最佳实践的书。 您可以在测试设计注意事项中找到一些很好的背景信息。 一般来说,你应该确保你的测试是:

  1. Using good locator strategies: When you are Interacting with the document, make sure that you use locators and page objects that are unlikely to change — if you have a testable element that you want to perform a test on, make sure that it has a stable ID, or position on the page that can be selected using a CSS selector, which isn't going to just change with the next site iteration. You want to make your tests as non-brittle as possible, i.e. they won't just break when something changes.
  2. Write atomic tests: Each test should test one thing only, making it easy to keep track of what test file is testing which criterion. As an example, the google_test.js test we looked at above is pretty good, as it just tests a single thing — whether the title of a search results page is set correctly. We could work on giving it a better name so it is easier to work out what it does if we add more google tests. Perhaps results_page_title_set_correctly.js would be slightly better?
  3. Write autonomous tests: Each test should work on it's own, and not depend on other tests to work.

此外,我们应该提到测试结果/报告 - 我们已经使用简单的 console.log()语句报告了我们上面的例子中的结果,但这一切都是在JavaScript中完成的,所以你可以使用任何 测试运行和度假系统,无论是 Mocha / chaijs.com/\">海 /其他种类的组合。

  1. For example, try making a local copy of our mocha_test.js example inside your project directory. Put it inside a subfolder called test. This example uses a long chain of promises to run all the steps required in our test — the promise-based methods WebDriver uses need to resolve for it to work properly.
  2. Install the mocha test harness by running the following command inside your project directory:
    npm install --save-dev mocha
  3. you can now run the test (and any others you put inside your test directory) using the following command:
    mocha --no-timeouts
  4. You should include the --no-timeouts flag to make sure your tests don't end up failing because of Mocha's arbitrary timeout (which is 3 seconds).

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

运行远程测试

事实证明,在删除服务器上运行测试不比在本地运行困难。 您只需要创建驱动程序实例,但需要指定一些其他功能,包括要测试的浏览器的功能,服务器的地址以及您需要访问的用户凭据(如果有)。

酱实验室

在Sauce Labs上远程运行Selenium测试很容易。 你需要的代码应该遵循下面看到的模式。

让我们写一个例子:

  1. Inside your project directory, create a new file called sauce_google_test.js.
  2. Give it the following contents
    var webdriver = require('selenium-webdriver'),
        By = webdriver.By,
        until = webdriver.until,
        username = "YOUR-USER-NAME",
        accessKey = "YOUR-ACCESS-KEY";
    
    var driver = new webdriver.Builder().
        withCapabilities({
          'browserName': 'chrome',
          'platform': 'Windows XP',
          'version': '43.0',
          'username': username,
          'accessKey': 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.findElement(By.name('btnG')).click();
    
    driver.sleep(2000).then(function() {
      driver.getTitle().then(function(title) {
        if(title === 'webdriver - Google Search') {
          console.log('Test passed');
        } else {
          console.log('Test failed');
        }
      });
    });
    
    driver.quit();
  3. From your Sauce Labs user settings, get your user name and access key. Replace the YOUR-USER-NAME and YOUR-ACCESS-KEY placeholders in the code with your actual user name and access key values (and make sure you keep them secure).
  4. Run your test with the following command:
    node sauce_google_test
    The test will be sent to Sauce Labs, and the test result will be returned to your console. This shows the importance of including some kind of result reporting mechanism!
  5. Now if you go to your Sauce Labs Automated Test dashboard page, you'll see your test listed; from here you'll be able to see videos, screenshots, and other such data.

注意:Sauce实验室的平台配置器 是一个有用的工具,用于根据要测试的浏览器/操作系统生成能力对象以供应给您的驱动程序实例。

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

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

为此,您需要:

  1. Install the Node Sauce Labs wrapper using the following command (if you've not already done it for this project):
    npm install saucelabs --save-dev
  2. Require saucelabs — put this at the top of your sauce_google_test.js file, just below the previous variable declarations:
    var SauceLabs = require('saucelabs');
  3. Create a new instance of SauceLabs, by adding the following just below that:
    var saucelabs = new SauceLabs({
        username : "YOUR-USER-NAME",
        password : "YOUR-ACCESS-KEY"
    });
    Again, replace the YOUR-USER-NAME and YOUR-ACCESS-KEY placeholders in the code with your actual user name and access key values (note that the saucelabs npm package rather confusingly uses password, not accessKey). Since you are using these twice now, you may want to create a couple of helper variables to store them in.
  4. Below the block where you define the driver variable (just below the build() line), add the following block — this gets the correct driver sessionID that we need to write data to the job (you can see it action in the next code block):
    driver.getSession().then(function (sessionid){
          driver.sessionID = sessionid.id_;
    });
  5. Finally, replace the driver.sleep(2000) ... block near the bottom of the code with the following:
    driver.sleep(2000).then(function() {
      driver.getTitle().then(function(title) {
        if(title === 'webdriver - Google Search') {
          console.log('Test passed');
          var testPassed = true;
        } else {
          console.log('Test failed');
          var testPassed = false;
        }
    
        saucelabs.updateJob(driver.sessionID, {
          name: 'Google search results page title test',
          passed: testPassed
        });
      });
    });

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

如果您现在返回到 Sauce Labs自动测试信息中心页面,您应该会立即看到您的新工作 具有附加的更新数据:

margin:0px auto; width:1088px;">

您自己的远程服务器

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

  1. The Selenium remote server requires Java to run. Download the latest JDK for your platform from the Java SE downloads page. Install it when it is downloaded.
  2. Next, download the latest Selenium standalone server — this acts as a proxy between your script and the browser drivers. Choose the latest stable version number (i.e. not a beta), and from the list choose a file starting with "selenium-server-standalone". When this has downloaded, put it in a sensible place, like in your home directory. If you've not already added the location to your PATH, do so now (see the Setting up Selenium in Node section).
  3. Run the standalone server by entering the following into a terminal on your server computer
    java -jar selenium-server-standalone-3.0.0.jar
    (update the .jar filename) so it matches exactly what file you've got.
  4. The server will run on http://localhost:4444/wd/hub — try going there now to see what you get.

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

  1. Create a copy of your google_test.js file, and call it google_test_remote.js; put it in your project directory.
  2. Update the second code block (which starts with var driver = ) like so
    var driver = new webdriver.Builder()
        .forBrowser('firefox')
        .usingServer('http://localhost:4444/wd/hub')
        .build();
  3. Run your test, and you should see it run as expected; this time however you will be runing it on the standalone server:
    node google_test_remote.js

所以这是很酷。 我们已在本地测试过,但您可以在任何服务器以及相关的浏览器驱动程序上进行设置,然后使用您选择的网址将脚本连接到它。

将硒与CI工具集成

另一点是,还可以将Selenium和Sauce Labs等相关工具与持续集成(CI)工具集成 - 这非常有用,因为它意味着您可以通过CI工具运行测试,并且只向代码提交新的更改 如果测试通过的话。

在本文中详细讨论此区域不在此范围内,但我们建议开始使用Travis CI - 这可能是开始使用的最简单的CI工具,并且与Web工具(如GitHub和Node

要开始,请参阅示例:

概要

这个模块应该已经被证明是有趣的,应该给你足够的洞察写入和运行自动化测试,让你去写自己的自动化测试。

Introduction to automated testing
JavaScript building blocks
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录
CSS

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }