我们都知道测试很重要,得益于 NativeSript 中对 Angular 12 的支持更新,在 NativeScript 的 Angular 项目中进行测试变得比以往更容易。
我们将逐步演示如何为示例的 SideDrawer Angular 模板添加测试。完成后,我们将拥有可以在我们选择的设备上执行的测试。
ns create
现在你已经拥有了一个可以构建并运行的项目,你可以使用 ns run android
进行检查。
我们需要一些代码来进行测试,所以让我们添加一个服务。
在 src/app/services
文件夹中创建一个名为 demo.service.ts
的文件
添加以下内容
import { Injectable } from '@angular/core'
@Injectable({
providedIn: 'root',
})
export class DemoService {
doSomething(): string {
return 'correct message'
}
}
这是一个简单的服务,我们可以将其注入到我们的控制器中,它只有一个返回值的函数。
将服务导入到搜索控制器(src/app/search/search.component.ts
)中
import {DemoService} from '../services/demo.service';
现在将服务注入到搜索控制器中
constructor(private demo: DemoService) {
// Use the component constructor to inject providers.
}
在搜索控制器中添加一个使用该服务的方法
doDemo(): string {
return this.demo.doSomething();
}
ns test init
选择 jasmine 框架
这将安装各种框架等。
如果你现在执行 ns test android
,你会得到编译错误,这是因为我们还没有配置 tsconfig.json
来编译示例测试。
配置 tsconfig.json 用于测试
添加一个名为 tsconfig.spec.json
的新文件(与 tsconfig.json 放在同一目录下),内容如下:
{
"extends": "./tsconfig.json",
"include": ["./src/tests/test-main.ts", "./src/tests/*.spec.ts", "./src/tests/**/*.spec.ts", "**/*.d.ts"]
}
这里我们扩展了现有的配置,但添加了我们的测试规范文件。
将 example.ts 重命名为 example.spec.ts(以符合我们在上一步中输入的内容)。
配置 webpack 在运行测试时使用新的 tsconfig.spec.json
在 webpack.config.js 中添加以下内容
if (env.unitTesting == true) {
webpack.chainWebpack((config) => {
config.plugin('AngularWebpackPlugin').tap((args) => {
args[0].tsconfig = './tsconfig.spec.json'
return args
})
})
}
这里我们在运行测试时(换句话说,当 env.unitTesting
为 true 时)将 tsconfig 文件设置为我们的特定测试文件。
现在我们可以执行示例测试。
启动 Android 模拟器
执行 ns test android
当你观察模拟器时,你会看到测试正在运行,然后应用程序退出。如果在执行完测试后还可以看到应用程序,以便我们可以查看详细信息等,那就更好了。
在 webpack.config.js
中,在上面添加的 chainWebpack
中添加以下内容。
const webpack = require('@nativescript/webpack')
const { merge } = require('webpack-merge')
module.exports = (env) => {
if (env.unitTesting == true) {
webpack.chainWebpack((config) => {
config.plugin('AngularWebpackPlugin').tap((args) => {
args[0].tsconfig = './tsconfig.spec.json'
return args
})
// keep the test runner open
config.plugin('DefinePlugin').tap((args) => {
args[0] = merge(args[0], {
__TEST_RUNNER_STAY_OPEN__: true,
})
return args
})
})
}
}
这将设置一个标志,在测试运行完成后让应用程序保持运行。
再次执行 ns test android
,你会看到所有测试都已完成。
我们在上面创建的服务由 Angular 注入到我们的组件中,因此我们需要使用 Angular TestBed 来测试我们的组件,并将这些服务提供给我们的测试。
添加设置代码
在 tests
文件夹中添加一个名为 test-main.ts
的新文件
添加以下内容
import '@nativescript/core/globals'
import '@nativescript/angular/polyfills'
import '@nativescript/zone-js/dist/pre-zone-polyfills'
import 'zone.js'
import '@nativescript/zone-js'
import 'zone.js/testing'
import { TestBed } from '@angular/core/testing'
import { NativeScriptTestingModule } from '@nativescript/angular/testing'
import { platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'
TestBed.initTestEnvironment([NativeScriptTestingModule], platformBrowserDynamicTesting())
更新 karma.config.js
以使用新文件
将 tests/test-main.ts
添加到 filePatterns
数组的开头。
为 Search 组件的 doDemo 函数添加测试。
在 tests
文件夹中添加一个名为 angular-example.spec.ts
的新文件,内容如下:
import { TestBed } from '@angular/core/testing'
import { SearchComponent } from '../app/search/search.component'
import { DemoService } from '../app/services/demo.service'
import { Page } from '@nativescript/core'
describe('search.component', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [SearchComponent],
providers: [DemoService, Page],
}).compileComponents()
})
it('should fail', async () => {
const fixture = TestBed.createComponent(SearchComponent)
const component = fixture.componentInstance as SearchComponent
expect(component.doDemo()).toEqual('angular-component-testing')
})
it('should succeed', async () => {
const fixture = TestBed.createComponent(SearchComponent)
const component = fixture.componentInstance as SearchComponent
expect(component.doDemo()).toEqual('correct message')
})
})
beforeEach
中,我们正在设置 TestBed,告诉它我们的组件以及它正常运行所需的服务提供者。运行 ns test android
现在会显示我们额外的测试,其中一些会失败。
由于这是一个实时监视测试模式,我们可以继续更改 "应该失败" 的测试以测试正确的值,保存文件,然后看到测试现在通过了。
供参考,示例项目可以在这里找到:https://github.com/jcassidyav/nativescript-testing-demo
如果你有一个为你的构建设置了 CI 环境,并且希望将测试纳入其中,这里有一些额外的提示……
一些 CI 环境允许你在构建过程中发布测试结果,例如在 Azure 中,你可以使用 发布测试任务 来发布结果。
为此,你需要配置一个报告器来输出测试结果。
karma.conf.js
文件中,将 'junit'
添加到报告器列表中例如:
reporters: ['progress', 'junit'],
junitReporter: {
outputDir: '../TestResults',
outputFile: 'TESTS_RESULTS.xml'
},
CI 环境在启动/关闭运行测试的模拟器实例方面带来了挑战。
如果你的 CI 设置为每次只运行一次测试,那么最好在每次运行的开始和结束时关闭模拟器。
将 -no-window
传递给 emulator.exe 会导致一个无头模拟器
你可以使用 adb 轮询模拟器,直到它启动后才能尝试运行测试。
例如,在 Windows PowerShell 上
do {
$outVar=cmd /c "C:\Android\android-sdk\platform-tools\adb.exe shell getprop sys.boot_completed" '2>&1'
$outVar=$outVar.Split([Environment]::NewLine) | Select -First 1
echo $outVar
Start-Sleep -Seconds 10
} Until ($outVar -eq "1")
Jason Cassidy 自 90 年代就开始开发软件,并在 2001 年帮助创立了总部位于 爱尔兰戈尔韦 的 Avaeon Solutions。