Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Angularで簡単な画面を単体テストまで一通り作った件
Search
ふるてつ
September 11, 2019
Programming
1.4k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Angularで簡単な画面を単体テストまで一通り作った件
ふるてつ
September 11, 2019
More Decks by ふるてつ
See All by ふるてつ
ユニットテストとE2Eテストをdemoしたい件
furutetsu
0
290
はじめてのSpringBoot
furutetsu
0
520
AngularとBootstrapを使った業務システムの設計について考えた。
furutetsu
1
2.5k
Other Decks in Programming
See All in Programming
複雑なUIコンポーネントとの ⻑い付き合い⽅:波及するバグからテスト戦略を経て、安全な再設計へ
mixplace
0
230
C#の現在地 進化の歴史と、AI時代の.NET Everywhere
neuecc
5
5k
月間100万人のサービス刷新で、 技術選定をHonoに振り切った話
yutobara
8
5.6k
GemmaをJevのように使ってみる / Use Gemma like Jev
kishida
5
740
re:Inventに行く前に知っておきたい現地参加のノウハウ
nokomoro3
0
390
IBM Bob Dojo #1 仕様駆動開発入門
oniak3ibm
PRO
0
360
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
500
[Rails World 2026] Durable orchestration on Rails: from continuation to workflow
palkan
1
510
モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった ? / is-the-business-domain-the-real-complexity
hatsu38
0
450
大喜利で理解するLLM as a Judge / Understanding LLM-as-a-Judge through Ogiri
rockname
0
200
Androidだけじゃない、DroidKaigiで広がった私の技術スタック
akkeylab
0
120
[ハンズオン]AIへの指示だけで「五目並べ」を作ってみよう
satoshi256kbyte
1
360
Featured
See All Featured
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.4k
The Curious Case for Waylosing
cassininazir
1
560
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
300
For a Future-Friendly Web
brad_frost
184
10k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
3k
What does AI have to do with Human Rights?
axbom
PRO
1
2.4k
Building Applications with DynamoDB
mza
96
7.2k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.9k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.6k
The Mindset for Success: Future Career Progression
greggifford
PRO
0
530
Building a Scalable Design System with Sketch
lauravandoore
464
34k
Information Architects: The Missing Link in Design Systems
soysaucechin
1
1.2k
Transcript
Angularで簡単な画面を 単体テストまで一通り作った件 Angular もくもく会 in Fukuoka #9 2019.9.11
自己紹介 福岡のエンジニアです。 客先常駐するタイプです。 COBOL → VB6.0 → VB.net → Spring
BootなIT人生。 他 jQuery → AngularJS → Angular 定年後の夢は、年金をもらいながら自称IT発明家になることです。 ふるてつ@tetsufuru19681 https://tetsufuru.hatenablog.com/ ちょくちょく参加するコミュニティ
今日のおはなし Angular Materialを使って簡単なマスタメンテ画面を作りました。 会社マスタメンテ画面とサービス 軽く動いたところで初テストコードを書きました。 Jasmineでサービス1つ、コンポーネント1つ 目新しいことは特にありませんが、せっかくなのでご紹介します。 ※HTML、CSSはまだあまりちゃんとしていません。
すこし実物を見ていただきます。
CompanyListComponent 検索条件:会社名、会社名カナ、削除フラグ ボタン:新規、クリア、検索 一覧:ページネーションあり、一覧をクリックすると詳細へジャンプ DIしているもの CompanyService(自前) FormBuilder Title Router
CompanyService メソッド getCompanyList(httpParams: HttpParams) getCompany(companySeq: number) createCompany(companyDto: CompanyDto) updateCompany(companyDto: CompanyDto)
DIしているもの HttpClient TranslateService ErrorMessageService(自前)
company.service.spec.ts(デフォルト) import { TestBed, inject } from '@angular/core/testing'; import {
CompanyService } from '../company/company.service'; xdescribe('CompanyService', () => { beforeEach(() => { TestBed.configureTestingModule({ providers: [CompanyService] }); }); it('should be created', inject([CompanyService], (service: CompanyService) => { expect(service).toBeTruthy(); })); });
company.service.spec.ts describe('CompanyService', () => { let companyService: CompanyService; let httpClientSpy:
{ get: jasmine.Spy, post: jasmine.Spy, put: jasmine.Spy }; let translateServiceSpy: { instant: jasmine.Spy }; beforeEach(() => { httpClientSpy = jasmine.createSpyObj('HttpClient', ['get', 'post', 'put']); translateServiceSpy = jasmine.createSpyObj('TranslateService', ['instant']); TestBed.configureTestingModule({ providers: [ CompanyService, ErrorMessageService, { provide: HttpClient, useValue: httpClientSpy }, { provide: TranslateService, useValue: translateServiceSpy },], }); companyService = TestBed.get(CompanyService); }); 追加 追加 追加
company.service.spec.ts it('#getCompanyList:should return expected SearchCompanyListDto (HttpClient called once)', () =>
{ const expectedSearchCompanyListDto: SearchCompanyListDto = new SearchCompanyListDto(); const searchCompanyDto: SearchCompanyDto[] = [{companySeq: BigInt('1'), companyName: 'companyName', ~ 中略 ~ updateUser: 'updateUser', updateTime: new Date}]; expectedSearchCompanyListDto.searchCompanyDtos = searchCompanyDto; httpClientSpy.get.and.returnValue(asyncData(expectedSearchCompanyListDto)); companyService.getCompanyList(null).subscribe( searchCompanyList => expect(searchCompanyList).toEqual(expectedSearchCompanyListDto, 'expected searchCompanyDto'),fail); expect(httpClientSpy.get.calls.count()).toBe(1, 'one call'); }); DTO SPY
company-list.component.spec.ts TestBed.configureTestingModule({ declarations: [CompanyListComponent], schemas: [NO_ERRORS_SCHEMA], imports: [ReactiveFormsModule, BrowserAnimationsModule, MaterialModule,
HttpClientModule, TranslateModule.forRoot({ loader: { provide: TranslateLoader, useFactory: HttpLoaderFactory, deps: [HttpClient] } }), ], providers: [ FormBuilder, ~ 以下略 ~ 追加 追加
company-list.component.spec.ts it('should entry company name', () => { const debugElement:
DebugElement = fixture.debugElement; const queriedElement = debugElement.query(By.css('#companyName')); const htmlInputElement: HTMLInputElement = queriedElement.nativeElement; const expectedEntry = 'abcd1234日本語'; htmlInputElement.value = expectedEntry; htmlInputElement.dispatchEvent(new Event('input')); expect(component.companyName.value).toEqual(expectedEntry); }); css selector event
テストした内容 company.service 4つのメソッド(getListXX、getXX、updateXX、createXX)×2(正常/エラー2通り) company-list.component TypeScript 「新規」「クリア」「検索」ボタンから呼ばれるメソッドのテスト 「結果一覧」リストをクリックした時に呼ばれるメソッドのテスト DOM 検索条件の項目名 検索条件の初期値
検索条件の入力値 検索用のhttpパラメータ値
None
None
課題・検討 無駄にspyを作った気がする。 [NO_ERRORS_SCHEMA]の使いどころをまだわかっていない。 DOMのテストの成果が良くわからない ⇒ DOMのカバレッジはない のか? Materialでidを追加したコードがブラウザで表示されると違うものに なる場合があった。 検索ボタンクリックのテストは
async ()=>でないと動かなかった。 DOMについて一覧のヘッダーやデータ行の内容を確認すべきか? 悩んだ。
参考サイト Material 環境:https://material.angular.io/guide/getting-started コントロール:https://material.angular.io/components/categories/forms 一覧関連:https://material.angular.io/components/categories/tables ページネーションのサンプル:https://material.angular.io/components/table/examples (上記URLの「Table retrieving data
through HTTP」にあります) テスト:https://angular.jp/guide/testing 上記URL内の「サービスのテスト」、「コンポーネントテストの基本」、「コンポーネントクラスのテスト」、「コンポーネント DOMのテスト」
わたしのブログ記事 Angular8 で Web アプリを作ろう - Jasmine - Serviceのテスト https://tetsufuru.hatenablog.com/entry/2019/08/13/130116
Angular8 で Web アプリを作ろう - Jasmine - Componentのテスト その1 https://tetsufuru.hatenablog.com/entry/2019/09/01/015709 Angular8 で Web アプリを作ろう - Jasmine - Componentのテスト その2 DOM https://tetsufuru.hatenablog.com/entry/2019/09/01/222413
ありがとうございました。