---
# System prepended metadata

title: Angular NG TEST語法紀錄
tags: [Angular]

---

### 常用語法

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`