我们在几个小时内部署自动化:TypeScript,Protractor,Jasmine

哈Ha!

我叫Vitaliy Kotov,我做过很多自动化测试,我喜欢它。 我最近参与了一个在TypeScript + Protractor + Jasmine堆栈上从头配置自动化的项目。 对我来说,这个堆栈是新的,我在Internet上搜索了必要的信息。

我设法只用英语找到了最有用,最明智的手册。 我认为俄语也需要这样做。 我只告诉您一些基础知识:为什么要这样的堆栈,需要配置什么以及最简单的测试是什么样的。

我必须马上说,我很少使用NodeJS,npm和一般的服务器端JavaScript(尤其是TypeScript)。 如果您发现某个地方的术语有误,或者我的某些决定可以改进,我将很高兴在经验丰富的专家的评论中了解到这一点。

顺便说一句,我已经有一篇类似的文章: “我们在几个小时内部署自动化:PHPUnit,Selenium,Composer”



挑战赛


首先,让我们弄清楚我们正在解决什么问题。 我们有一个使用AngularJS编写的Web应用程序。 这是一个JavaScript框架,经常基于该框架编写Web项目。

在本文中,我们将不考虑AngularJS项目的利弊。 关于为此类项目编写端到端测试的几句话。

测试自动化的一个相当重要的方面是使用页面元素,这是在定位器的帮助下发生的。 定位器是根据某些规则组成并标识一个或多个UI元素的线。

对于Web,最常用的是CSS和Xpath。 有时,如果页面上有一个具有唯一ID的元素,则可以通过它进行搜索。 但是,在我看来,WebDriver最终仍将此ID转换为CSS定位器,并且已经在使用它。

如果我们看一些AngularJS项目的HTML代码,我们将看到很多经典HTML元素以外的属性:



该代码来自量角器演示页面。

AngularJS使用所有以ng- *开头的属性来处理UI。 一个相当典型的情况是,除了这些控制属性以外的元素都没有其他元素,这使质量定位器的编译过程变得复杂。

那些做了很多自动化工作的人都知道可以轻松构建定位器的此类UI的价值。 毕竟,这对于大型项目而言很少见。 :)

实际上,对于这样的项目,我们还需要配置测试自动化。 走吧

什么是什么


首先,让我们弄清楚为什么需要堆栈中的每个组件。

量角器是基于WebDriverJS的测试框架。 将由他启动我们的浏览器,使它们打开必要的页面并与必要的元素进行交互。

该框架是专门为AngularJS项目量身定制的。 它提供了其他方法来指定定位器:

element(by.model('first')); element(by.binding('latest')); element(by.repeater('some')); 

完整列表可以在手册页上找到。

这些方法简化了项目中定位器的创建和支持。 但是,您必须了解,在任何情况下“全部”都将转换为css。 事实是,WebDriver中进行交互的W3C协议只能与一组有限的定位器一起使用。 可以在w3.org上查看此列表。

TypeScript是Microsoft创建的一种编程语言。 TypeScript与JavaScript的不同之处在于其键入变量的能力,对使用完整类的支持以及连接模块的能力。

与V8引擎配合使用的TS代码编写的代码已转换为JS代码,该代码已经在执行。 在此转换过程中,将检查代码是否符合要求。 例如,如果将某个字符串而不是int显式传递给某个地方的函数,则它不会“编译”。

Jasmine是用于测试JavaScript代码的框架。 实际上,多亏了他,我们的JS代码才变成了我们所谓的测试。 他负责管理这些测试。

下面我们看一下它的功能。

组装和项目设置


好吧,我们决定了一套框架,现在让我们把整个事情放在一起。

为了使用该代码,我选择了Microsoft的Visual Studio Code 。 尽管许多人用WebStorm甚至是JetBrains的Intellij Idea编写。

我已经安装了NodeJS(v11.6.0)和NPM(6.9.0)。 如果没有的话,这不是问题;安装它们并不困难。 一切在官方网站上都有足够详细的描述。

可以使用纱线代替NPM,尽管这对于小型项目而言并不重要。

在我们的IDE中,我们正在创建一个新项目。 我们在项目的根目录中创建package.json-在其中将描述项目所需的所有软件包。

您可以使用npm init命令创建它。 或者,您可以简单地将内容复制到文件中。

最初, package.json如下所示:

 { "name": "protractor", "dependencies": { "@types/node": "^10.5.2", "@types/jasmine": "^3.3.12", "protractor": "^5.4.2", "typescript": "^3.4.1" } } 

之后,我们执行npm install命令来安装所有必需的模块及其依赖项(好吧,您还记得有关比黑洞重的东西的图片……)

结果,我们应该有一个node_modules目录。 如果她出现了,那么一切都按计划进行。 如果没有,那么值得研究一下命令执行的结果,通常所有内容都在此处进行了详细描述。

TypeScript及其配置


要安装TypeScript,我们需要npm:

 npm install -g typescript 

确保已安装:

 $ tsc -v Version 3.4.1 

一切似乎井井有条。

现在,我们需要创建一个用于使用TS的配置。 它也应该位于项目的根目录,并称为tsconfig.json。

其内容将如下所示:

 { "compilerOptions": { "lib": ["es6"], "strict": true, "outDir" : "output_js", "types" : ["jasmine", "node"] }, "exclude": [ "node_modules/*" ] } 

简而言之,我们在此配置中指定了以下内容:

  • 将最终的JS代码放在哪个目录中(在本例中为output_js)
  • 启用严格模式
  • 表明我们正在使用哪些框架
  • 编译中排除的node_modules

TS具有多种设置。 这些足以满足我们的项目需求。 您可以在typescriptlang.org上了解更多信息。

现在让我们看一下tsc命令的工作原理 ,它将把我们的TS代码变成JS代码。 为此,请创建一个包含以下内容的简单check_tsc.ts文件:

 saySomething("Hello, world!"); function saySomething(message: string) { console.log(message); } 

然后执行tsc命令(为此,您需要在项目目录中)。

我们将看到我们具有output_js目录,并且其中包含以下内容的类似js文件已出现:

 "use strict"; saySomething("Hello, world!"); function saySomething(message) { console.log(message); } 

该文件已经可以使用node命令启动:

 $ node output_js/check_tsc.js Hello, world! 

因此,我们编写了第一个TypeScipt程序,恭喜。 现在让我们编写测试。 :)

量角器配置


对于量角器,我们还需要一个配置。 但它不再是json形式,而是ts文件形式。 让我们将其称为config.ts并在其中编写以下代码:

 import { Config } from "protractor"; export const config: Config = { seleniumAddress: "http://127.0.0.1:4444/wd/hub", SELENIUM_PROMISE_MANAGER: false, capabilities: { browserName: "chrome", /*chromeOptions: { args: [ "--headless", "--window-size=800,600" ] }*/ }, specs: [ "Tests/*Test.js", ] }; 

在此文件中,我们指定了以下内容:

首先,是运行中的Selenium服务器的路径。 运行起来非常简单,您只需下载Standalone Server jar文件和必要的驱动程序(例如Chrome浏览器的chrome驱动程序)。 接下来,编写以下命令:

 java -jar -Dwebdriver.chrome.driver=/path/to/chromedriver /path/to/selenium-server-standalone.jar 

结果,我们应该看到以下结论:

 23:52:41.691 INFO [GridLauncherV3.launch] - Selenium build info: version: '3.11.0', revision: 'e59cfb3' 23:52:41.693 INFO [GridLauncherV3$1.launch] - Launching a standalone Selenium Server on port 4444 2019-05-02 23:52:41.860:INFO::main: Logging initialized @555ms to org.seleniumhq.jetty9.util.log.StdErrLog 23:52:42.149 INFO [SeleniumServer.boot] - Welcome to Selenium for Workgroups.... 23:52:42.149 INFO [SeleniumServer.boot] - Selenium Server is up and running on port 4444 

默认端口4444。 可以使用-port参数或通过配置参数“ seleniumArgs” =>“ -port”进行设置。

如果您想要更轻松,更快捷:可以下载npm软件包webdriver-manager

然后使用启动,关闭等命令管理服务器。 并没有太大的区别,只是我更习惯于使用jar文件。 :)

其次 ,我们表示我们不想使用Promise管理器。 稍后再详细介绍。

第三 ,我们为浏览器指定了功能。 例如,我注释了一部分,我们很容易以无头模式启动浏览器。 这是一个很酷的功能,但是它不允许您直观地观察我们的测试。 同时,我们正在学习-我想。 :)

第四 ,我们为规格(测试)指定了一个掩码。 一切都位于Tests文件夹中,并以Test.js结尾。 为什么在js而不是ts上? 这是因为最后,Node将专门用于JS文件,而不适用于TS文件。 重要的是不要混淆,尤其是在工作开始时。

现在创建Tests文件夹并编写第一个测试。 他将执行以下操作:

  • 禁用检查这是一个Angular页面。 否则,我们会收到以下错误消息:运行testForAngular时出错。 当然,对于“角度页面”,不需要关闭此检查。
  • 转到Google页面。
  • 检查是否有文本输入字段。
  • 输入文本“量角器”。
  • 单击提交按钮(它有一个相当复杂的定位器,因为有两个按钮,第一个是不可见的)。
  • 可以预期URL将包含“量角器”一词-这意味着我们做对了所有事情,然后开始搜索。

这是我得到的代码:

 import { browser, by, element, protractor } from "protractor"; describe('Search', () => { it('Open google and find a text', async () => { //       let EC = protractor.ExpectedConditions; //    AngularJS await browser.waitForAngularEnabled(false); //   Google await browser.get('https://www.google.com/'); //    css = input[role='combobox'] let input_button = element(by.css("input[role='combobox']")); //     ( presenceOf) await browser.wait(EC.presenceOf(input_button), 5000); //     “protractor” await input_button.sendKeys("protractor"); //      css let submit_button = element(by.css(".FPdoLc input[type='submit'][name='btnK']")); //      ( ,     input-,   ) await browser.wait(EC.presenceOf(submit_button), 5000); //     await submit_button.click(); // ,  URL    'protractor' await browser.wait(EC.urlContains('protractor'), 5000); }); }); 

在代码中,我们看到一切都以describe()函数开头。 她来自茉莉花框架。 这是我们脚本的包装。 在它内部,可能有功能beforeAll()和beforeEach()在所有测试之前和每个测试之前执行任何操作。 实际上,它所测试的功能与()一样多。 最后,如果已定义,则将在每个测试和所有测试之后执行afterAll()和afterEach()进行操作。

我不会谈论Jasmine的所有功能,您可以在jasmine.imtqy.com网站上阅读有关它们的信息

要运行我们的测试,您首先需要将TS代码转换为JS代码,然后运行它:

 $ tsc $ protractor output_js/config.js 

我们的测试开始了-我们很棒。 :)



如果测试没有开始,则值得检查:

  • 该代码编写正确。 通常,如果代码中存在严重错误,我们将在tsc命令期间捕获它们。
  • 该Selenium服务器正在运行。 为此,您可以打开URL http: //127.0.0.1-00-00444/wd/hub-应该有一个Selenium会话接口。
  • 该Chrome通常从下载的chrome-driver版本开始。 为此,请在wd /集线器/页面上,单击创建会话,然后选择Chrome。 如果无法启动,则您需要更新Chrome或下载其他版本的chrome驱动程序。
  • 如果所有操作均失败,则可以验证npm install命令是否已成功完成。
  • 如果所有内容均正确编写,但仍然没有任何内容-尝试搜索该错误。 它通常会有所帮助。 :)

NPM脚本


为了使生活更轻松,您可以使命令的一部分成为npm别名。 例如,我想删除具有先前JS文件的目录,并在每次测试运行之前使用新的JS文件重新创建该目录。

为此,请将脚本项添加到package.json中:

 { "name": "protractor", "scripts": { "test": "rm -rf output_js/; tsc; protractor output_js/config.js" }, "dependencies": { "@types/node": "^10.5.2", "@types/jasmine": "^3.3.12", "protractor": "^5.4.2", "typescript": "^3.4.1" } } 

现在输入npm test命令将发生以下情况:带有旧代码的output_js目录将被删除,将重新创建该目录,并将新的JS代码写入其中。 之后,测试将立即开始。

除了这组命令,您还可以指定其他您个人需要使用的命令。 例如,您可以在两次测试运行之间启动和终止硒服务器。 尽管这当然更容易在测试代码内部进行控制。

关于承诺


最后,我将讨论Promise,异步/等待以及NodeJS中的测试编写与相同的Java或Python有何不同。

JavaScript是一种异步语言。 这意味着代码并不总是按照编写顺序执行。 这包括HTTP请求,我们记得该代码通过HTTP与Selenium Server通信。

承诺(通常称为“承诺”)提供了一种组织异步代码的便捷方法。 您可以在learning.javascript.ru上了解有关它们的更多信息。

实际上,这些对象使一个代码依赖于另一代码的执行,从而保证了一定的顺序。 量角器会非常积极地处理这些对象。

让我们来看一个例子。 假设我们执行以下代码:

 driver.findElement().getText(); 

在Java中,我们希望我们返回String类型的对象。 在量角器中,情况并非如此,我们将返回一个Promise对象。 就像那样,以调试为目标进行打印将不起作用。

通常我们不需要打印结果值。 我们需要将其传递给已经可以使用该值的其他方法。 例如,它将检查文本是否符合预期。

Protractor中类似的方法也接受Promise对象作为输入,因此没有问题。 但是,如果您仍然想查看该值,则()将派上用场。

这是我们可以在Google页面上打印按钮文本的方式(请注意,由于这是一个按钮,因此文本位于value属性内):

 //   let submit_button = element(by.css(".FPdoLc input[type='submit'][name='btnK']")); //    await browser.wait(EC.presenceOf(submit_button), 5000); //   then()   await submit_button.getAttribute("value").then((text) => { console.log(text); }); 

至于async / await关键字,这是使用异步代码的一种较新的方法。 它使您可以避免由于大量嵌套而先前在代码中形成的promise hell。 不过,您将无法完全摆脱Promise,需要与他们合作。 这是可以理解和详细的,可以在JavaScript中设计异步/等待:优势,陷阱和使用功能中找到

家庭作业


作为一项家庭作业,我建议为用AngularJS编写的页面编写测试: protractor-demo

不要忘记从代码中删除有关在AngularJS上关闭页面检查的行。 并确保使用专门为AngularJS设计的定位器。 这没有什么特别的魔术,但是很方便。

总结


让我们盘点一下。 我们设法编写了可以在TypeScript + Protractor + Jasmine上运行的测试。 我们学习了如何构建这样的项目,创建必要的配置,并编写了第一个测试。

在此过程中,我们讨论了有关使用JavaScript自动测试的一些知识。 几个小时似乎很好。 :)

阅读什么,在哪里看


量角器具有相当不错的手册,其中包含JavaScript示例: https//www.protractortest.org/#/tutorial
茉莉花有手册: https : //jasmine.imtqy.com/pages/docs_home.html
TypeScipt有一个很好的入门: https : //www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html

在媒介上,有一篇关于TypeScript + Protractor + Cucumber的英文很好的文章: https : //medium.com/@igniteram/e2e-testing-with-protractor-cucumber-using-typescript-564575814e4a

在我的存储库中,我发布了本文讨论的最终代码: https : //github.com/KotovVitaliy/HarbProtractorJasmineJasmine

在Internet上,您可以找到此堆栈上更复杂和更大项目的示例。

感谢您的关注! :)

Source: https://habr.com/ru/post/zh-CN451522/


All Articles