测试
当一个
@betway东盟体育appionic /角
应用程序是使用Ionic CLI生成的,它会自动设置用于单元测试和端到betway东盟体育app端测试应用程序。这与Angular CLI使用的设置相同。指的是
角测试指南
以获取关于测试Angular应用的详细信息。
测试的原则
在测试应用程序时,最好记住,测试可以显示系统中是否存在缺陷。然而,要证明任何非平凡系统完全没有缺陷是不可能的。因此,测试的目标不是验证代码是否正确,而是发现代码中的问题。这是一个微妙但重要的区别。
如果我们开始证明代码是正确的,那么我们更有可能坚持代码的正确路径。如果我们开始寻找问题,我们更有可能更全面地执行代码,并找到潜伏在那里的bug。
最好从一开始就对应用程序进行测试。这允许在过程的早期发现缺陷,当它们更容易修复时。这也允许在向系统添加新特性时自信地重构代码。
单元测试
单元测试独立于系统的其他部分执行单个代码单元(组件、页面、服务、管道等)。隔离是通过注入模拟对象而不是代码依赖项来实现的。模拟对象允许测试细粒度地控制依赖项的输出。模拟还允许测试确定调用了哪些依赖项,以及向它们传递了什么。
编写良好的单元测试的结构是这样的,代码单元和它包含的特性通过
描述()
回调。对代码单元及其特性的需求通过
它()
回调。当描述为
描述()
而且
它()
回调函数被读取,它们作为一个短语有意义。当描述为嵌套时
描述()
S和final
它()
连接在一起,它们构成一个完整描述测试用例的句子。
由于单元测试是隔离地执行代码的,因此它们快速、健壮,并允许高度的代码覆盖率。
使用模拟
单元测试隔离地执行代码模块。为此,我们建议使用Jasmine ( https://jasmine.github.io/ ).Jasmine创建模拟对象(Jasmine将其称为“间谍”),以在测试时取代依赖关系。当使用模拟对象时,测试可以控制调用该依赖项返回的值,从而使当前测试独立于对该依赖项所做的更改。这也使得测试设置更容易,允许测试只关注被测试模块内的代码。
使用模拟还允许测试查询模拟,以确定它是否被调用以及如何通过
toHaveBeenCalled *
的一组功能。这些函数的测试应该尽可能具体,有利于调用
toHaveBeenCalledTimes
在调用
toHaveBeenCalled
当测试某个方法被调用时。这是
期望(mock.foo) .toHaveBeenCalledTimes (1)
比
期望(mock.foo) .toHaveBeenCalled ()
.在测试未被调用的东西时,应遵循相反的建议(
期望(mock.foo) .not.toHaveBeenCalled ()
).
在Jasmine中创建模拟对象有两种常见方法。可以使用从头构造模拟对象
jasmine.createSpy
而且
jasmine.createSpyObj
或者间谍可以安装到现有的对象使用
spyOn ()
而且
spyOnProperty ()
.
使用
jasmine.createSpy
而且
jasmine.createSpyObj
jasmine.createSpyObj
使用在创建时定义的一组模拟方法从头创建一个完整的模拟对象。这很有用,因为它非常简单。测试不需要构造或注入任何内容。使用这个函数的缺点是,它允许创建与实际对象不匹配的对象。
jasmine.createSpy
类似,但它创建了一个独立的模拟函数。
使用
spyOn ()
而且
spyOnProperty ()
spyOn ()
在现有对象上安装间谍。使用这种技术的好处是,如果试图监视对象上不存在的方法,就会引发异常。这可以防止测试模拟不存在的方法。缺点是测试需要从一个完全形成的对象开始,这可能会增加所需的测试设置量。
spyOnProperty ()
相似的不同之处在于,它监视的是属性而不是方法。
通用测试结构
单元测试包含在
规范
文件与一个
规范
每个实体(组件、页面、服务、管道等)的文件。的
规范
文件与它们正在测试的源文件并列,并以源文件命名。例如,如果项目有一个名为WeatherService的服务,则该服务的代码在一个名为
weather.service.ts
测试在一个名为
weather.service.spec.ts
.这两个文件都在同一个文件夹里。
的
规范
文件本身包含一个
描述
调用它定义了整个测试。嵌套在它里面的是其他的
描述
定义主要功能领域的调用。每一个
描述
调用可以包含安装和拆卸代码(通常通过
beforeEach
而且
afterEach
调用),更
描述
形成功能分层分解的调用
它
定义单个测试用例的调用。
的
描述
而且
它
调用还包含一个描述性文本标签。在结构良好的测试中,
描述
而且
它
调用结合它们的标签来为每个测试用例执行适当的短语和完整的标签,通过结合
描述
而且
它
标签,创建一个完整的句子。
例如:
描述
(
“计算”
,
(
)
= >
{
描述
(
“分”
,
(
)
= >
{
它
(
“正确计算4 / 2”
(
)
= >
{
}
)
;
它
(
“懦夫拒绝除以零”
(
)
= >
{
}
)
;
...
}
)
;
描述
(
“乘”
,
(
)
= >
{
...
}
)
;
}
)
;
外
描述
调用声明
计算
服务正在经受考验,内在
描述
调用确切地说明正在测试的功能
它
调用声明测试用例是什么。当运行每个测试用例的完整标签是一个有意义的句子(懦弱的计算除法拒绝除以零)。
页面和组件
页面只是Angular组件。因此,页面和组件都使用 角的组件测试 指导方针。
因为页面和组件同时包含TypeScript代码和HTML模板标记,所以可以同时执行组件类测试和组件DOM测试。创建页面时,生成的模板测试如下所示:
进口
{
CUSTOM_ELEMENTS_SCHEMA
}
从
“@angular /核心”
;
进口
{
异步
,
ComponentFixture
,
试验台
}
从
“@angular /核心/测试”
;
进口
{
TabsPage
}
从
”。/ tabs.page '
;
描述
(
“TabsPage”
,
(
)
= >
{
让
组件
:
TabsPage
;
让
夹具
:
ComponentFixture
<
TabsPage
>
;
beforeEach
(
异步
(
)
= >
{
试验台
.
configureTestingModule
(
{
声明
:
[
TabsPage
]
,
模式
:
[
CUSTOM_ELEMENTS_SCHEMA
]
,
}
)
.
compileComponents
(
)
;
}
)
;
beforeEach
(
(
)
= >
{
夹具
=
试验台
.
createComponent
(
TabsPage
)
;
组件
=
夹具
.
componentInstance
;
夹具
.
detectChanges
(
)
;
}
)
;
它
(
“应该创建”
,
(
)
= >
{
预计
(
组件
)
.
toBeTruthy
(
)
;
}
)
;
}
)
;
在进行组件类测试时,组件对象是通过定义的组件对象来访问的
组件= fixture.componentInstance;
.这是组件类的一个实例。在进行DOM测试时
fixture.nativeElement
使用属性。这是实际的
HTMLElement
对于组件,它允许测试使用标准的HTML API方法,例如
HTMLElement.querySelector
以检查DOM。
服务
服务通常分为两大类:执行计算和其他操作的实用服务,以及主要执行HTTP操作和数据操作的数据服务。
基本服务测试
测试大多数服务的建议方法是实例化服务,并手动为服务具有的任何依赖项注入模拟。这样,就可以对代码进行隔离测试。
假设有一个服务,它的方法是获取一组考勤卡并计算净工资。我们还假设税收计算是通过当前服务依赖的另一个服务处理的。这种薪给服务可以这样测试:
进口
{
PayrollService
}
从
”。/ payroll.service '
;
描述
(
“PayrollService”
,
(
)
= >
{
让
服务
:
PayrollService
;
让
taxServiceSpy
;
beforeEach
(
(
)
= >
{
taxServiceSpy
=
茉莉花
.
createSpyObj
(
“TaxService”
,
{
federalIncomeTax
:
0
,
stateIncomeTax
:
0
,
社会保障
:
0
,
医疗保险
:
0
}
)
;
服务
=
新
PayrollService
(
taxServiceSpy
)
;
}
)
;
描述
(
“净工资计算”
,
(
)
= >
{
...
}
)
;
}
)
;
这允许测试通过模拟设置(比如)控制各种税收计算返回的值
taxServiceSpy.federalIncomeTax.and.returnValue (73.24)
.这使得“净收入”测试独立于税收计算逻辑。税号变更时,只需变更与税务服务相关的代码和测试。对净薪酬的测试可以继续进行下去,因为这些测试不关心如何计算税收,只关心正确地应用价值。
在通过以下方式生成服务时使用的搭建
betway东盟体育app离子型服务名称
使用Angular的测试工具并建立一个测试模块。这样做并不是绝对必要的。但是,这些代码可以保留,这样就可以手动构建或注入服务:
进口
{
试验台
,
注入
}
从
“@angular /核心/测试”
;
进口
{
PayrollService
}
从
”。/ payroll.service '
;
进口
{
TaxService
}
从
”。/ tax.service '
;
描述
(
“PayrolService”
,
(
)
= >
{
让
taxServiceSpy
;
beforeEach
(
(
)
= >
{
taxServiceSpy
=
茉莉花
.
createSpyObj
(
“TaxService”
,
{
federalIncomeTax
:
0
,
stateIncomeTax
:
0
,
社会保障
:
0
,
医疗保险
:
0
}
)
;
试验台
.
configureTestingModule
(
{
供应商
:
[
PayrollService
,
{
提供
:
TaxService
,
useValue
:
taxServiceSpy
}
]
}
)
;
}
)
;
它
(
"在注射的地方做一些测试"
,
注入
(
[
PayrollService
]
,
(
服务
:
PayrollService
)
= >
{
预计
(
服务
)
.
toBeTruthy
(
)
;
}
)
)
;
它
(
“在手动构建的地方进行一些测试”
,
(
)
= >
{
常量
服务
=
新
PayrollService
(
taxServiceSpy
)
;
预计
(
服务
)
.
toBeTruthy
(
)
;
}
)
;
}
)
;
测试HTTP数据服务
大多数执行HTTP操作的服务都会使用Angular的HttpClient服务来执行这些操作。对于这样的测试,建议使用Angular的测试
HttpClientTestingModule
.要了解该模块的详细文档,请参阅Angular的
Angular测试HTTP请求
指南。
这个测试的基本设置如下:
进口
{
HttpBackend
,
HttpClient
}
从
“@angular /共同/ http”
;
进口
{
HttpTestingController
,
HttpClientTestingModule
}
从
“@angular /共同/ http /测试”
;
进口
{
试验台
,
注入
}
从
“@angular /核心/测试”
;
进口
{
IssTrackingDataService
}
从
”。/ iss-tracking-data.service '
;
描述
(
“IssTrackingDataService”
,
(
)
= >
{
让
httpClient
:
HttpClient
;
让
httpTestingController
:
HttpTestingController
;
让
issTrackingDataService
:
IssTrackingDataService
;
beforeEach
(
(
)
= >
{
试验台
.
configureTestingModule
(
{
进口
:
[
HttpClientTestingModule
]
,
供应商
:
[
IssTrackingDataService
]
}
)
;
httpClient
=
试验台
.
得到
(
HttpClient
)
;
httpTestingController
=
试验台
.
得到
(
HttpTestingController
)
;
issTrackingDataService
=
新
IssTrackingDataService
(
httpClient
)
;
}
)
;
它
(
“存在”
,
注入
(
[
IssTrackingDataService
]
,
(
服务
:
IssTrackingDataService
)
= >
{
预计
(
服务
)
.
toBeTruthy
(
)
;
}
)
)
;
描述
(
“位置”
,
(
)
= >
{
它
(
"现在得到国际空间站的位置"
,
(
)
= >
{
issTrackingDataService
.
位置
(
)
.
订阅
(
x
= >
{
预计
(
x
)
.
toEqual
(
{
经度
:
-
138.1719
,
纬度
:
44.4423
}
)
;
}
)
;
常量
要求的事情
=
httpTestingController
.
expectOne
(
“http://api.open-notify.org/iss-now.json”
)
;
预计
(
要求的事情
.
请求
.
方法
)
.
toEqual
(
“得到”
)
;
要求的事情
.
冲洗
(
{
iss_position
:
{
经度
:
“-138.1719”
,
纬度
:
“44.4423”
}
,
时间戳
:
1525950644
,
消息
:
“成功”
}
)
;
httpTestingController
.
验证
(
)
;
}
)
;
}
)
;
}
)
;
管道
管道类似于具有特定定义接口的服务。它是一个包含一个公共方法的类,
变换
,它操作输入值(和其他可选参数),以便创建在页面上呈现的输出。要测试管道:实例化管道,调用transform方法,并验证结果。
作为一个简单的例子,让我们看看一个采用
人
对象并格式化名称。为了简单起见,我们设a
人
由一个
id
,
firstName
,
姓
,
middleInitial
.该管道的要求是将名称打印为“Last, First m”,以处理名、姓或中间首字母不存在的情况。这样的测试可能是这样的:
进口
{
NamePipe
}
从
”。/ name.pipe '
;
进口
{
人
}
从
“. . / . . /模型/人”
;
描述
(
“NamePipe”
,
(
)
= >
{
让
管
:
NamePipe
;
让
testPerson
:
人
;
beforeEach
(
(
)
= >
{
管
=
新
NamePipe
(
)
;
testPerson
=
{
id
:
42
,
firstName
:
“道格拉斯。”
,
姓
:
“亚当斯”
,
middleInitial
:
“N”
}
;
}
)
;
它
(
“存在”
,
(
)
= >
{
预计
(
管
)
.
toBeTruthy
(
)
;
}
)
;
它
(
'正确格式化全名'
,
(
)
= >
{
预计
(
管
.
变换
(
testPerson
)
)
.
toBeEqual
(
“道格拉斯亚当斯,N。”
)
;
}
)
;
它
(
'句柄中间没有首字母'
,
(
)
= >
{
删除
testPerson
.
middleInitial
;
预计
(
管
.
变换
(
testPerson
)
)
.
toBeEqual
(
“亚当斯,道格拉斯。”
)
;
}
)
;
它
(
“处理没有名字”
,
(
)
= >
{
删除
testPerson
.
firstName
;
预计
(
管
.
变换
(
testPerson
)
)
.
toBeEqual
(
“亚当斯N。”
)
;
}
)
;
它
(
“处理没有姓”
,
(
)
= >
{
删除
testPerson
.
姓
;
预计
(
管
.
变换
(
testPerson
)
)
.
toBeEqual
(
“道格拉斯N。”
)
;
}
)
;
}
)
;
在使用管道的组件和页面中通过DOM测试来使用管道也是有益的。
端到端测试
端到端测试用于验证应用程序作为一个整体工作,通常包括到实时数据的连接。单元测试单独关注代码单元,从而允许对应用程序逻辑进行低级测试,而端到端测试则关注各种用户故事或使用场景,提供贯穿应用程序的整体数据流的高级测试。单元测试试图发现应用程序逻辑的问题,而端到端测试试图发现当这些单独的单元一起使用时发生的问题。端到端测试揭示了应用程序整体架构的问题。
由于端到端测试测试的是用户故事,并且覆盖整个应用程序,而不是单独的代码模块,所以端到端测试存在于项目中自己的应用程序中,而不是主应用程序本身的代码中。大多数端到端测试通过自动化与应用程序的常见用户交互并检查DOM来确定这些交互的结果来进行操作。
测试结构
当一个
@betway东盟体育appionic /角
中生成一个默认的端到端测试应用程序
e2e
文件夹中。这个应用程序使用
量角器
来控制浏览器和
茉莉花
构造并执行测试。该应用程序最初由四个文件组成:
protractor.conf.js
—Protractor配置文件tsconfig.e2e.json
-测试应用程序的特定TypeScript配置src / app.po.ts
-一个页面对象,包含导航应用程序的方法,DOM中的查询元素,以及操作页面上的元素src / app.e2e-spec.ts
-一个测试脚本
页面对象
端到端测试通过自动化与应用程序的常见用户交互来进行操作,等待应用程序响应,并检查DOM以确定交互的结果。这涉及到大量的DOM操作和检查。如果这些都是手动完成的,那么测试将非常脆弱,难以阅读和维护。
页面对象将单个页面的HTML封装在一个TypeScript类中,提供了一个测试脚本用来与应用程序交互的API。在页面对象中封装DOM操作逻辑使测试更具可读性,并且更容易推理,从而降低了测试的维护成本。创建精心设计的页面对象是创建高质量和可维护的端到端测试的关键。
基本页面对象
许多测试依赖于诸如等待页面可见、在输入中输入文本以及单击按钮等操作。用于实现此目的的方法只与用于更改适当DOM元素的CSS选择器保持一致。因此,有必要将此逻辑抽象为一个基类,供其他页面对象使用。
下面是一个实现了所有页面对象都需要支持的一些基本方法的示例。
进口
{
浏览器
,
通过
,
元素
,
ExpectedConditions
}
从
“量角器”
;
出口
类
PageObjectBase
{
私人
路径
:
字符串
;
受保护的
标签
:
字符串
;
构造函数
(
标签
:
字符串
,
路径
:
字符串
)
{
这
.
标签
=
标签
;
这
.
路径
=
路径
;
}
负载
(
)
{
返回
浏览器
.
得到
(
这
.
路径
)
;
}
rootElement
(
)
{
返回
元素
(
通过
.
css
(
这
.
标签
)
)
;
}
waitUntilInvisible
(
)
{
浏览器
.
等待
(
ExpectedConditions
.
invisibilityOf
(
这
.
rootElement
(
)
)
,
3000
)
;
}
waitUntilPresent
(
)
{
浏览器
.
等待
(
ExpectedConditions
.
presenceOf
(
这
.
rootElement
(
)
)
,
3000
)
;
}
waitUntilNotPresent
(
)
{
浏览器
.
等待
(
ExpectedConditions
.
不
(
ExpectedConditions
.
presenceOf
(
这
.
rootElement
(
)
)
)
,
3000
)
;
}
waitUntilVisible
(
)
{
浏览器
.
等待
(
ExpectedConditions
.
visibilityOf
(
这
.
rootElement
(
)
)
,
3000
)
;
}
getTitle
(
)
{
返回
元素
(
通过
.
css
(
`
$ {
这
.
标签
}
ion-title
`
)
)
.
getText
(
)
;
}
受保护的
enterInputText
(
选取
:
字符串
,
文本
:
字符串
)
{
常量
埃尔
=
元素
(
通过
.
css
(
`
$ {
这
.
标签
}
$ {
选取
}
`
)
)
;
常量
可使
=
埃尔
.
元素
(
通过
.
css
(
“输入”
)
)
;
可使
.
sendKeys
(
文本
)
;
}
受保护的
enterTextareaText
(
选取
:
字符串
,
文本
:
字符串
)
{
常量
埃尔
=
元素
(
通过
.
css
(
`
$ {
这
.
标签
}
$ {
选取
}
`
)
)
;
常量
可使
=
埃尔
.
元素
(
通过
.
css
(
“文本区域”
)
)
;
可使
.
sendKeys
(
文本
)
;
}
受保护的
clickButton
(
选取
:
字符串
)
{
常量
埃尔
=
元素
(
通过
.
css
(
`
$ {
这
.
标签
}
$ {
选取
}
`
)
)
;
浏览器
.
等待
(
ExpectedConditions
.
elementToBeClickable
(
埃尔
)
)
;
埃尔
.
点击
(
)
;
}
}
页面的抽象
应用程序中的每个页面都有自己的页面对象类,用于抽象该页上的元素。如果使用基页对象类,创建页对象主要涉及为特定于该页的元素创建自定义方法。通常,这些定制元素利用基类中的方法来执行所需的工作。
下面是一个简单但典型的登录页面的示例页面对象。注意,许多方法,例如
enterEMail ()
,调用基类中的方法来执行大部分工作。
进口
{
浏览器
,
通过
,
元素
,
ExpectedConditions
}
从
“量角器”
;
进口
{
PageObjectBase
}
从
”。/ base.po '
;
出口
类
LoginPage
扩展
PageObjectBase
{
构造函数
(
)
{
超级
(
“app-login”
,
/登录的
)
;
}
waitForError
(
)
{
浏览器
.
等待
(
ExpectedConditions
.
presenceOf
(
元素
(
通过
.
css
(
' . error '
)
)
)
,
3000
)
;
}
getErrorMessage
(
)
{
返回
元素
(
通过
.
css
(
' . error '
)
)
.
getText
(
)
;
}
enterEMail
(
电子邮件
:
字符串
)
{
这
.
enterInputText
(
“# email-input”
,
电子邮件
)
;
}
enterPassword
(
密码
:
字符串
)
{
这
.
enterInputText
(
“#密码输入”
,
密码
)
;
}
clickSignIn
(
)
{
这
.
clickButton
(
“# signin-button”
)
;
}
}
测试脚本
与单元测试类似,端到端测试脚本由嵌套组成
描述()
而且
它()
功能。在端到端测试的情况下
描述()
函数通常用
它()
在该场景中执行的函数表示应用程序应该表现为操作的特定行为。
控件中使用的标签也类似于单元测试
描述()
而且
它()
函数应该在“描述”或“它”以及连接在一起形成完整的测试用例时都有意义。
下面是一个示例端到端测试脚本,它演示了一些典型的登录场景。
进口
{
AppPage
}
从
“. . /页面对象/页面/ app.po”
;
进口
{
AboutPage
}
从
“. . /页面对象/页面/ about.po”
;
进口
{
CustomersPage
}
从
“. . /页面对象/页面/ customers.po”
;
进口
{
LoginPage
}
从
“. . /页面对象/页面/ login.po”
;
进口
{
MenuPage
}
从
“. . /页面对象/页面/ menu.po”
;
进口
{
TasksPage
}
从
“. . /页面对象/页面/ tasks.po”
;
描述
(
“登录”
,
(
)
= >
{
常量
关于
=
新
AboutPage
(
)
;
常量
应用程序
=
新
AppPage
(
)
;
常量
客户
=
新
CustomersPage
(
)
;
常量
登录
=
新
LoginPage
(
)
;
常量
菜单
=
新
MenuPage
(
)
;
常量
任务
=
新
TasksPage
(
)
;
beforeEach
(
(
)
= >
{
应用程序
.
负载
(
)
;
}
)
;
描述
(
“之前登录”
,
(
)
= >
{
它
(
'显示登录屏幕'
,
(
)
= >
{
预计
(
登录
.
rootElement
(
)
.
isDisplayed
(
)
)
.
toEqual
(
真正的
)
;
}
)
;
它
(
'允许应用程序内导航到大约'
,
(
)
= >
{
菜单
.
clickAbout
(
)
;
关于
.
waitUntilVisible
(
)
;
登录
.
waitUntilInvisible
(
)
;
}
)
;
它
(
“不允许应用程序内导航到任务”
,
(
)
= >
{
菜单
.
clickTasks
(
)
;
应用程序
.
waitForPageNavigation
(
)
;
预计
(
登录
.
rootElement
(
)
.
isDisplayed
(
)
)
.
toEqual
(
真正的
)
;
}
)
;
它
(
“不允许应用内导航到客户”
,
(
)
= >
{
菜单
.
clickCustomers
(
)
;
应用程序
.
waitForPageNavigation
(
)
;
预计
(
登录
.
rootElement
(
)
.
isDisplayed
(
)
)
.
toEqual
(
真正的
)
;
}
)
;
它
(
'如果登录失败将显示错误消息'
,
(
)
= >
{
登录
.
enterEMail
(
“test@test.com”
)
;
登录
.
enterPassword
(
“假的”
)
;
登录
.
clickSignIn
(
)
;
登录
.
waitForError
(
)
;
预计
(
登录
.
getErrorMessage
(
)
)
.
toEqual
(
“密码无效或用户没有密码”
)
;
}
)
;
它
(
'如果登录成功,则导航到任务页面'
,
(
)
= >
{
登录
.
enterEMail
(
“test@test.com”
)
;
登录
.
enterPassword
(
“测试”
)
;
登录
.
clickSignIn
(
)
;
任务
.
waitUntilVisible
(
)
;
}
)
;
}
)
;
描述
(
“一次登录”
,
(
)
= >
{
beforeEach
(
(
)
= >
{
任务
.
waitUntilVisible
(
)
;
}
)
;
它
(
“允许导航到客户页面”
,
(
)
= >
{
菜单
.
clickCustomers
(
)
;
客户
.
waitUntilVisible
(
)
;
任务
.
waitUntilInvisible
(
)
;
}
)
;
它
(
'允许导航到关于页面'
,
(
)
= >
{
菜单
.
clickAbout
(
)
;
关于
.
waitUntilVisible
(
)
;
任务
.
waitUntilInvisible
(
)
;
}
)
;
它
(
'允许导航回任务页面'
,
(
)
= >
{
菜单
.
clickAbout
(
)
;
任务
.
waitUntilInvisible
(
)
;
菜单
.
clickTasks
(
)
;
任务
.
waitUntilVisible
(
)
;
}
)
;
}
)
;
}
)
;
配置
默认配置与此相同
environment.ts
用于开发的文件。为了更好地控制端到端测试所使用的数据,为测试创建一个特定的环境并使用该环境进行测试通常是有用的。本节将展示创建此配置的一种可能方法。
测试环境
设置测试环境包括创建一个新的环境文件,该文件使用专用的测试后端,更新
angular.json
文件来使用该环境,并修改
e2e
脚本的
package.json
指定
测验
环境。
创建
environment.e2e.ts
文件
角
environment.ts
而且
environment.prod.ts
文件通常用于存储应用程序后端数据服务的基本URL等信息。创建一个
environment.e2e.ts
它提供相同的信息,只是连接到专门用于测试的后端服务,而不是开发或生产后端服务。下面是一个例子:
出口
常量
环境
=
{
生产
:
假
,
databaseURL
:
“https://e2e-test-api.my-great-app.com”
,
projectId
:
“my-great-app-e2e”
}
;
修改
angular.json
文件
的
angular.json
需要修改文件才能使用该文件。这是一个分层的过程。按照下面列出的xpath添加所需的配置。
添加配置
/项目/应用程序/建筑师/构建/配置
被称为
测验
执行文件替换:
“测试”
:
{
“fileReplacements”
:
[
{
“替换”
:
“src /环境/ environment.ts”
,
”与“
:
“src /环境/ environment.e2e.ts”
}
]
}
添加配置
/项目/ app /建筑师/服务/配置
被称为
测验
将浏览器目标指向
测验
构建上面定义的配置。
“测试”
:
{
“browserTarget”
:
“应用程序:构建:测试”
}
添加配置
/项目/ app-e2e /建筑师/ e2e /配置
被称为
测验
这将开发服务器目标指向
测验
服务上面定义的配置。
“测试”
:
{
“devServerTarget”
:
“应用程序服务:测试”
}
修改
package.json
文件
修改
package.json
文件,这样
npm e2e运行
使用
测验
配置。
“脚本”
:
{
“e2e”
:
“ng e2e——配置=测试”
,
“棉絮”
:
“ng线头”
,
“ng”
:
“ng”
,
“开始”
:
“ng服务”
,
“测试”
:
“ng测试”
,
“测试:开发”
:
“ng测试——浏览器= ChromeHeadlessCI”
,
“测试:ci”
:
"ng test——no-watch——browsers=ChromeHeadlessCI"
}
,
测试清理
如果端到端测试以任何方式修改数据,那么在测试完成后将数据重置为已知状态是有帮助的。一种方法是:
- 创建执行清理的端点。
-
添加一个
onCleanUp ()
函数配置
对象导出的protractor.conf.js
文件。
下面是一个例子:
onCleanUp
(
)
{
常量
axios
=
需要
(
“axios”
)
;
返回
axios
.
帖子
(
“https://e2e-test-api.my-great-app.com/purgeDatabase”
,
{
}
)
.
然后
(
res
= >
{
控制台
.
日志
(
res
.
数据
)
;
}
)
.
抓
(
犯错
= >
控制台
.
日志
(
犯错
)
)
;
}