### 常用語法 Lint a single file Angular CLI v8 ```DOS= ng lint --files src/app/app.component.ts ``` Angular CLI v10.1.7+ ```DOS= ng lint --lint-file-patterns src/app/app.component.ts ``` 在src下生成html測報 ```DOS= ng test --code-coverage ``` 在src下生成html測報(指定路徑,好像不吃絕對路徑,所以先cd到專案目錄src所在層) ```DOS= ng test --code-coverage --include src/unit/test.spec.ts ``` 在src下生成html測報(指定路徑,CLI v9↓) ```DOS= ng test --main src/unit/test.spec.ts ``` *排除指定路徑則用-exclude *預設–watch為true會在code修改後自動觸發一輪測試 斷點測試流程: 1. ng test 2. 跳出的瀏覽器頁面點debug按鈕 3. F12 → cmd+p → 找要測的component及其spec → 設定好想要的斷點 4. 5F **ng test通常是一個對應compenent的spec.ts檔案** ```javascript= import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { BackupListComponent } from './backup-list.component'; import { DebugElement } from '@angular/core'; describe('HorizontalGridComponent test', () => { let component: HorizontalGridComponent; let fixture: ComponentFixture<HorizontalGridComponent>; // 設定 TestBed 環境 beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ HttpClientTestingModule ], declarations: [HorizontalGridComponent], }).compileComponents(); })); beforeEach(() => { // new 你想要測的 Component fixture = TestBed.createComponent(HorizontalGridComponent); // 使用 fixture.componentInstance 扮演發動測試的角色 component = fixture.componentInstance; // 使用 fixture.detectChanges() 偵測是否有變動被觸發 fixture.detectChanges(); }); it('should create', () => { expect(fixture).toBeDefined(); expect(component).toBeDefined(); }); it('should have <h3> with "Hello"', () => { // const El: HTMLElement = fixture.nativeElement; const De: DebugElement = fixture.debugElement; const El: HTMLElement = De.nativeElement; // nativeElement相當於debugElement的一個屬性 // js原生的querySelector api去獲取h3標籤 const p = El.querySelector('h3'); // 判斷h3標籤的內容 expect(p.textContent).toEqual('Hello'); }); it('should find the <h3> with fixture.debugElement.query(By.css)', () => { const De: DebugElement = fixture.debugElement; const El = De.query(By.css('h3')); // nativeElement相當於debugElement的一個屬性 // js原生的querySelector api去獲取h3標籤 const p: HTMLElement = El.nativeElement; // 判斷h3標籤的內容 expect(p.textContent).toEqual('Hello'); }); afterEach(() => { TestBed.resetTestingModule(); }); }); ``` CLI 會產生 Jasmine 和 Karma 的設定檔,主要包括karma.conf.js和test.ts。 karma.conf.js設定環境,test.ts決定跑哪些script **test.ts** ``` javascript= import 'zone.js/dist/zone-testing'; import { getTestBed } from '@angular/core/testing'; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; declare const require: any; // First, initialize the Angular testing environment. getTestBed().initTestEnvironment( BrowserDynamicTestingModule, platformBrowserDynamicTesting() ); // Then we find all the tests. const context = require.context('./', true, /\.spec\.ts$/); // And load the modules. context.keys().map(context); ``` **karma.conf.js** ``` javascript= module.exports = function (config) { config.set({ basePath: '', frameworks: ['jasmine', '@angular-devkit/build-angular'], plug×××: [ require('karma-jasmine'), require('karma-chrome-launcher'), require('karma-jasmine-html-reporter'), require('karma-coverage-istanbul-reporter'), require('@angular-devkit/build-angular/plug×××/karma') ], client: { clearContext: false // leave Jasmine Spec Runner output visible in browser }, coverageIstanbulReporter: { dir: require('path').join(__dirname, '../coverage'), reports: ['html', 'lcovonly'], fixWebpackSourcePaths: true }, reporters: ['progress', 'kjhtml'], port: 9876, colors: true, logLevel: config.LOG_INFO, autoWatch: true, browsers: ['Chrome'], singleRun: false }); }; ``` ### 常用Method describe(string, function): Jasmine 的廣域函數,可以理解為一個測試組(Test Suite),用來劃分單元測試。 it(string, function):可以理解為測項。Specs 用 it 的廣域函數來定義。每個 Spec 包含一個或多個 expectations 期望值來測試。 Jasmine 中的每個 expectation 是一個斷言,可以是 true 或者 false。當每個 Spec 中的所有 expectations 都是 true,則通過測試。 beforeEach() 在 describe 函數中每個 Spec(it)執行之前執行。 afterEach() 在 describe 函數中每個 Spec(it)執行之後執行。 beforeAll() 在 describe 函數中所有的 Spec(it)執行之前執行一次。 afterAll() 在 describe 函數中所有的 Spec(it)執行之後執行一次。 xdescribe:跳過整個測試組 xit:跳過該 it fdescribe 和 fit:只測試特定對象 spy:監測任何 function 的呼叫和參數的呼叫痕跡,不會影響函數真實返回值,配合 2 個特殊的 Matcher 如下 toHaveBeenCalled 可以檢查 function 是否被呼叫過 toHaveBeenCalledWith 可以檢查傳入參數是否被作為參數呼叫過 ```Jacascript= describe("spy", function() { var foo, bar = null; beforeEach(function() { foo = { setBar: function(value) { bar = value; } }; spyOn(foo, 'setBar'); foo.setBar(123); foo.setBar(456, 'another param'); }); it("追蹤函式呼叫情況", function() { // 上面 了foo.setBar,所以返回true expect(foo.setBar).toHaveBeenCalled(); // 上面呼叫了foo.setBar,並且傳入參數123,所以返回true expect(foo.setBar).toHaveBeenCalledWith(456, 'another param'); // Spy的呼叫並不會影響真實的值,所以bar仍然是null。 expect(bar).toBeNull(); }); }); ``` ###### tags: `Angular`