講者:Chris 江江
Jasmine: 提供撰寫測試所需的工具, 搭配測試運行框架在瀏覽器上執行測試。
Karma : 測試運行框架,為開發中執行 unit test 的好選擇。(紅燈、綠燈、重構)
Protractor: End to End Test專用。模擬使用者的操作,來判斷程式在瀏覽器上正常與否。
專門用來撰寫 Javascript 測試的框架
完全不依賴於其他的 Javascript 框架
語法輕巧且明確,撰寫容易
describe('單元測試一',()=>{
beforeEach(()=>{ ... });
it('案例一',()=>{ ... });
it('案例二',()=>{ ... });
afterEach(()=>{ ... });
});
Karma 是個既簡單又快速的測試框架, 旨在幫助開發人員能夠迅速的進行自動化單元測試。
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular/cli'],
file:[ 'src/app/**/**.spec.ts'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular/cli/plugins/karma')
],
client:{
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: true
},
angularCli: {
environment: 'dev'
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false
});
};
frameworks: 所使用的框架
files: 要測試的目錄
plugins: 依賴的第三方套件
reporters:
browser: 想測試的瀏覽器, 需搭配plugins
coverageIstanbulReporter: 覆蓋率測試報告
autoWatch: 自動監測檔案是否變更
singleRun: 預設為false, 若為true則會在測試完成時關閉瀏覽器
TestBed.configureTestingModule({
declarations: [
AppComponent
]
});
將TestBed設定放到beforeEach內,
即可確保每次測試執行前環境都回到最初預設的狀態
BeforeEach(()=>{
TestBed.configureTestingModule({
declarations: [
AppComponent
]
});
});
當我們要測試AppComponent時,
Angular會根據Component是否採用templateUrl與styleUrls來決定要不要發XHR。若有,則需採用async的方式來進行編譯。
BeforeEach(async(()=>{
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
fixture.componentInstance == fixture.debugElement.componentInstance;
fixture.nativeElement == fixture.debugElement.nativeElement;
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelectorAll('h1')[0].textContent)
.toContain('Chris\' Book Store');
}));
TestBed.configureTestingModule({
declarations: [ NovelComponent ],
providers: [{ provide: ExampleService, useValue: fakeService }]
})
const fakeService = {
getNovel: () => {
return Observable.of({
"returnCode": 200,
"data": [
{
"bookname": "Titanic",
"price": 900
},
{
"bookname": "Once",
"price": 550
},
{
"bookname": "Harry Potter",
"price": 1380
}
]
})
}
};
TestBed.configureTestingModule({
imports: [RouterTestingModule],
declarations: [
AppComponent
]
}).compileComponents();
TestBed.configureTestingModule({
imports: [HttpClientModule],
providers: [ExampleService]
});
//方法1 注入service同時也catch它
beforeEach(inject([ExampleService], (eService) => {
fakeExampleService = eService;
}));
//方法2 測試時再注入service
it('should get the right response, too', inject([ExampleService], (service: ExampleService) => {
let fakeResponse = null;
service.getNovel().subscribe(res=>{
fakeResponse = res.data;
expect(fakeResponse[0].bookname).toBe('Titanic');
});
}));
import { TestBed, fakeAsync } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { Router } from '@angular/router';
import { Location } from '@angular/common';
const routes = [
{
path: '', component: null,
children: [
{ path: '', redirectTo: 'novel', pathMatch: 'full' },
{ path: 'novel', component: NovelComponent },
{ path: 'comic', component: ComicComponent },
{ path: 'magazine', component: MagazineComponent },
{ path: '**', redirectTo: 'novel' }
]
}
];
beforeEach(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule.withRoutes(routes)],
declarations: [
NovelComponent,
ComicComponent,
MagazineComponent,
AppComponent
]
});
//取得注入的Router與Location
router = TestBed.get(Router);
location = TestBed.get(Location);
fixture = TestBed.createComponent(AppComponent);
router.initialNavigation();
});
it('should go to Comic book page', fakeAsync(() => {
router.navigate(['comic']).then(()=>{
expect(location.path()).toBe('/comic');
});
}));
輸入以下指令
ng test --code-coverage
Angular將會在專案目錄下生成 coverage資料夾