はじめに
Angular開発において、単体テストはアプリケーションの品質を確保する重要なプロセスです。AngularではデフォルトでJasmineとKarmaが設定されており、これらを使うことで簡単にテスト環境を構築できます。この記事では、JasmineとKarmaの基本を理解し、コンポーネントやサービスの単体テストを実装する方法を解説します。
目次
- JasmineとKarmaとは?
- Angularのテスト環境のセットアップ
- 基本的なJasmineの構文
- コンポーネントの単体テスト
- サービスの単体テスト
- 実践:簡単なテストケースの作成
- トラブルシューティングとベストプラクティス
1. JasmineとKarmaとは?
-
Jasmine
- JavaScriptのテストフレームワーク。BDD(振る舞い駆動開発)スタイルで記述できる。
- シンプルな構文で、テストケースの記述が容易。
-
Karma
- テストランナー。ブラウザでテストを実行し、結果をリアルタイムで確認できる。
- Angular CLIに組み込まれており、セットアップ不要で利用可能。
2. Angularのテスト環境のセットアップ
Angular CLIで生成されたプロジェクトには、すでにJasmineとKarmaが設定されています。
テストの実行方法
ng test
これにより、Karmaが起動し、テストがブラウザ上で実行されます。
テストファイル
- ファイル名:
*.spec.ts
- 各コンポーネントやサービスのテストファイルが自動生成されます。
3. 基本的なJasmineの構文
テストケースの基本構造
describe('テストスイート名', () => {
it('テストケース名', () => {
expect(true).toBe(true);
});
});
マッチャの例
-
toBe
:厳密な等価性を確認 -
toEqual
:オブジェクトの値を比較 -
toContain
:配列や文字列に特定の要素が含まれるかを確認
expect(1 + 1).toBe(2);
expect({ name: 'Angular' }).toEqual({ name: 'Angular' });
expect([1, 2, 3]).toContain(2);
4. コンポーネントの単体テスト
コンポーネントのテストでは、テンプレートのレンダリングやユーザーイベントの処理を確認します。
テスト対象コンポーネント
@Component({
selector: 'app-my-component',
template: `<button (click)="increment()">Click me</button><p>{{ count }}</p>`
})
export class MyComponent {
count = 0;
increment() {
this.count++;
}
}
テストケース
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MyComponent } from './my-component.component';
describe('MyComponent', () => {
let component: MyComponent;
let fixture: ComponentFixture<MyComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [MyComponent]
}).compileComponents();
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should increment count on button click', () => {
const button = fixture.nativeElement.querySelector('button');
button.click();
fixture.detectChanges();
expect(component.count).toBe(1);
});
});
5. サービスの単体テスト
サービスはビジネスロジックやデータ取得を扱う重要な部分です。
テスト対象サービス
@Injectable({
providedIn: 'root',
})
export class MyService {
getMessage(): string {
return 'Hello, Service!';
}
}
テストケース
import { TestBed } from '@angular/core/testing';
import { MyService } from './my-service.service';
describe('MyService', () => {
let service: MyService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(MyService);
});
it('should return correct message', () => {
expect(service.getMessage()).toBe('Hello, Service!');
});
});
6. 実践:簡単なテストケースの作成
以下の例では、ToDoアプリのテストを実装します。
テスト対象
@Component({
selector: 'app-todo',
template: `<input [(ngModel)]="newTask"><button (click)="addTask()">Add</button><ul><li *ngFor="let task of tasks">{{ task }}</li></ul>`
})
export class TodoComponent {
tasks: string[] = [];
newTask = '';
addTask() {
if (this.newTask.trim()) {
this.tasks.push(this.newTask);
this.newTask = '';
}
}
}
テストケース
it('should add a task to the list', () => {
component.newTask = 'Test Task';
component.addTask();
expect(component.tasks).toContain('Test Task');
});
7. トラブルシューティングとベストプラクティス
-
テストが失敗する場合の対処法
-
TestBed
の設定を見直す。 - 非同期処理の場合、
async
やfakeAsync
を活用する。
-
-
ベストプラクティス
- テストを小さく、独立したものにする。
- 可能な限りモックを使用して依存関係をテスト対象から分離する。
おわりに
JasmineとKarmaを使えば、Angularアプリケーションの単体テストを効率的に実施できます。この記事で紹介した方法を参考に、ぜひプロジェクトにテストを導入してみてください。