Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Unit Testing in Angular

Unit Testing in Angular

Ac4189b770a4dbc0078935a68fff6f5c?s=128

Ciro Nunes

April 13, 2016
Tweet

More Decks by Ciro Nunes

Other Decks in Programming

Transcript

  1. UNIT TESTING

  2. Ciro Nunes FRONTEND ENGINEER @cironunesdev

  3. Belo Horizonte

  4. Berlin

  5. None
  6. None
  7. DO YOU DEVELOP WEB APPS?

  8. DO THEY HAVE MORE THAN 10 FEATURES?

  9. ARE YOU CONFIDENT REFACTORING YOUR CODE?

  10. None
  11. None
  12. UNIT TESTS

  13. UNIT TESTS are

  14. UNIT TESTS automatic are

  15. UNIT TESTS automatic fast are

  16. UNIT TESTS automatic fast are documentation

  17. 1. Unit testing 101 2. Setup Angular testing environment 3.

    Test Angular services and components AGENDA
  18. UNIT TESTING 101

  19. None
  20. expect(calc.add(10,.5)).toBe(15);

  21. class.Calculator.{. ..add(firstNumber,.secondNumber).{. ....return.firstNumber.+.secondNumber;. ..}. } calculator.ts

  22. import.{Calculator}.from.'./calculator';. describe('Calculator',.().=>.{. ..let.calc;. ... ..beforeEach(().=>.{. ....calc.=.new.Calculator();. ..});. ... ..it('sums.two.numbers',.().=>.{. ....expect(calc.add(2,.5)).toBe(7);.

    ..});. }); calculator.spec.ts
  23. import.{Calculator}.from.'./calculator';. describe('Calculator',.().=>.{. ..let.calc;. ... ..beforeEach(().=>.{. ....calc.=.new.Calculator();. ..});. ... ..it('sums.two.numbers',.().=>.{. ....expect(calc.add(2,.5)).toBe(7);.

    ..});. }); calculator.spec.ts
  24. import.{Calculator}.from.'./calculator';. describe('Calculator',.().=>.{. ..let.calc;. ... ..beforeEach(().=>.{. ....calc.=.new.Calculator();. ..});. ... ..it('sums.two.numbers',.().=>.{. ....expect(calc.add(2,.5)).toBe(7);.

    ..});. }); calculator.spec.ts
  25. import.{Calculator}.from.'./calculator';. describe('Calculator',.().=>.{. ..let.calc;. ... ..beforeEach(().=>.{. ....calc.=.new.Calculator();. ..});. ... ..it('sums.two.numbers',.().=>.{. ....expect(calc.add(2,.5)).toBe(7);.

    ..});. }); calculator.spec.ts
  26. import.{Calculator}.from.'./calculator';. describe('Calculator',.().=>.{. ..let.calc;. ... ..beforeEach(().=>.{. ....calc.=.new.Calculator();. ..});. ... ..it('sums.two.numbers',.().=>.{. ....expect(calc.add(2,.5)).toBe(7);.

    ..});. }); calculator.spec.ts Executed 1 of 1 SUCCESS
  27. describe('Calculator',.().=>.{. ..describe('#add',.().=>.{});. ..describe('#subtract',.().=>.{});. ..describe('#multiply',.().=>.{});. ..describe('#divide',.().=>.{});. }); calculator.spec.ts http://betterspecs.org/

  28. describe('Calculator',.().=>.{. ..beforeEach(...);. ..describe('#add',.().=>.{. ....it('sums.two.numbers',.().=>.{. ......expect(calc.add(2,.5)).toBe(7);. ....});. ....it('sums.three.numbers',.().=>.{. ......expect(calc.add(5,.10,.20)).toBe(35);. ....});. ..});.

    }); calculator.spec.ts
  29. describe('Calculator',.().=>.{. ..beforeEach(...);. ..describe('#add',.().=>.{. ....it('sums.two.numbers',.().=>.{. ......expect(calc.add(2,.5)).toBe(7);. ....});. ....it('sums.three.numbers',.().=>.{. ......expect(calc.add(5,.10,.20)).toBe(35);. ....});. ..});.

    }); calculator.spec.ts
  30. describe('Calculator',.().=>.{. ..beforeEach(...);. ..describe('#add',.().=>.{. ....it('sums.two.numbers',.().=>.{. ......expect(calc.add(2,.5)).toBe(7);. ....});. ....it('sums.three.numbers',.().=>.{. ......expect(calc.add(5,.10,.20)).toBe(35);. ....});. ..});.

    }); calculator.spec.ts Executed 2 of 2 (1 FAILED)
  31. calculator.ts class.Calculator.{. ..add(...numbers).{. ....return.numbers.reduce((current,.total).=>.{. ......return.current.+.total;. ....},.0);. ..}. }

  32. calculator.ts class.Calculator.{. ..add(...numbers).{. ....return.numbers.reduce((current,.total).=>.{. ......return.current.+.total;. ....},.0);. ..}. } Executed 2

    of 2 SUCCESS
  33. 1. Keep tests small as possible (single purpose) 2. Test

    the public interfaces STRATEGIES
  34. Whenever you can, write unit tests. They are cheap, fast

    and they can run often.
  35. SETUP THE ENVIRONMENT

  36. None
  37. ANGULAR CLI https://github.com/angular/angular-cli

  38. $.npm.install.Og.angularOcli

  39. $.ng.new.testOproject

  40. ├──.angularOcliObuild.js. ├──.angularOcli.json. ├──.config. ├──.e2e. ├──.karmaOtestOshim.js. ├──.karma.conf.js. ├──.package.json. ├──.protractor.conf.js. ├──.public. ├──.src.

    ├──.tslint.json. ├──.typings. └──.typings.json
  41. ├──.angularOcliObuild.js. ├──.angularOcli.json. ├──.config. ├──.e2e. ├──.karmaOtestOshim.js. ├──.karma.conf.js. ├──.package.json. ├──.protractor.conf.js. ├──.public. ├──.src.

    ├──.tslint.json. ├──.typings. └──.typings.json └──.client. ....├──.app. ....│...├──.routeOconfig.ts. ....│...├──.testOproject.html. ....│...├──.testOproject.spec.ts. ....│...└──.testOproject.ts. ....├──.app.ts. ....├──.favicon.ico. ....├──.index.html. ....├──.tsconfig.json. ....└──.typings.d.ts
  42. $.ng.test

  43. $.ng.serve

  44. TESTING ANGULAR

  45. COMPONENTS

  46. @Component({. ..selector:.'taOuser'. }). export.class.TaUser.{. ..@Input().user;. ..@Input().msg;. } ta-user.ts

  47. <h1.*ngIf="user">. . {{.user.name.}}.is.{{.user.age.}}.and.his.favorite.color.is.. . {{.user.favoriteColor.}}. </h1>. <h2.*ngIf="msg">{{.msg.}}</h2> ta-user.html

  48. import.{. ..it,. ..describe,. ..expect,. ..injectAsync,. ..TestComponentBuilder. }.from.'angular2/testing';. import.{TaUser}.from.'./taOuser'; ta-user.spec.ts

  49. import.{. ..it,. ..describe,. ..expect,. ..injectAsync,. ..TestComponentBuilder. }.from.'angular2/testing';. import.{TaUser}.from.'./taOuser'; ta-user.spec.ts

  50. import.{. ..it,. ..describe,. ..expect,. ..injectAsync,. ..TestComponentBuilder. }.from.'angular2/testing';. import.{TaUser}.from.'./taOuser'; ta-user.spec.ts Inject

    providers in it blocks
  51. import.{. ..it,. ..describe,. ..expect,. ..injectAsync,. ..TestComponentBuilder. }.from.'angular2/testing';. import.{TaUser}.from.'./taOuser'; ta-user.spec.ts

  52. import.{. ..it,. ..describe,. ..expect,. ..injectAsync,. ..TestComponentBuilder. }.from.'angular2/testing';. import.{TaUser}.from.'./taOuser'; ta-user.spec.ts Instantiate

    components in it blocks
  53. import.{. ..it,. ..describe,. ..expect,. ..injectAsync,. ..TestComponentBuilder. }.from.'angular2/testing';. import.{TaUser}.from.'./taOuser'; ta-user.spec.ts

  54. import.{. ..it,. ..describe,. ..expect,. ..injectAsync,. ..TestComponentBuilder. }.from.'angular2/testing';. import.{TaUser}.from.'./taOuser'; ta-user.spec.ts

  55. describe('TaUser.Component',.().=>.{. ..it('should.show.the.user.info',. ....injectAsync([TestComponentBuilder],(tcb:TestComponentBuilder).=>.{ ta-user.spec.ts

  56. describe('TaUser.Component',.().=>.{. ..it('should.show.the.user.info',. ....injectAsync([TestComponentBuilder],(tcb:TestComponentBuilder).=>.{. ....return.tcb.createAsync(TaUser).then((fixture).=>.{. ......let.componentInstance.=.fixture.componentInstance;. ......let.element.=.fixture.nativeElement;. ......componentInstance.user.=.{.name:.'Ciro',.age:.18,.favoriteColor:.'black'.};. ......fixture.detectChanges();. ......expect(element.querySelector('h1').innerText). .........toBe('Ciro.is.18.and.his.favorite.color.is.black');.

    ....});. ..})); ta-user.spec.ts
  57. ComponentFixture componentInstance nativeElement debugElement elementRef detectChanges() destroy()

  58. SERVICES

  59. @Injectable(). export.class.TaUserService.{. ..getUser(username:.string).{. ....return.new.Promise((resolve,.reject).=>.{. ......let.user.=.users.filter(u.=>.u.name.===.username);. ......if.(user.length).{. ........resolve(user[0]);. ......}.else.{. ........reject('Not.found.');. ......}.

    ....});. ..}. } ta-user-service.spec.ts
  60. import.{. ..it,. ..describe,. ..expect,. ..beforeEachProviders,. ..inject,. ..fakeAsync,. ..tick. }.from.'angular2/testing';. import.{TaUserService}.from.'./taOuserOservice';

    ta-user-service.spec.ts
  61. import.{. ..it,. ..describe,. ..expect,. ..beforeEachProviders,. ..inject,. ..fakeAsync,. ..tick. }.from.'angular2/testing';. import.{TaUserService}.from.'./taOuserOservice';

    ta-user-service.spec.ts Loads the providers using Angular's DI
  62. import.{. ..it,. ..describe,. ..expect,. ..beforeEachProviders,. ..inject,. ..fakeAsync,. ..tick. }.from.'angular2/testing';. import.{TaUserService}.from.'./taOuserOservice';

    ta-user-service.spec.ts
  63. import.{. ..it,. ..describe,. ..expect,. ..beforeEachProviders,. ..inject,. ..fakeAsync,. ..tick. }.from.'angular2/testing';. import.{TaUserService}.from.'./taOuserOservice';

    ta-user-service.spec.ts Inject the loaded providers in the it block
  64. import.{. ..it,. ..describe,. ..expect,. ..beforeEachProviders,. ..inject,. ..fakeAsync,. ..tick. }.from.'angular2/testing';. import.{TaUserService}.from.'./taOuserOservice';

    ta-user-service.spec.ts
  65. import.{. ..it,. ..describe,. ..expect,. ..beforeEachProviders,. ..inject,. ..fakeAsync,. ..tick. }.from.'angular2/testing';. import.{TaUserService}.from.'./taOuserOservice';

    ta-user-service.spec.ts Allows to test asynchronous in a sync fashion
  66. import.{. ..it,. ..describe,. ..expect,. ..beforeEachProviders,. ..inject,. ..fakeAsync,. ..tick. }.from.'angular2/testing';. import.{TaUserService}.from.'./taOuserOservice';

    ta-user-service.spec.ts
  67. describe('TaUserService.Service',.().=>.{. ..beforeEachProviders(().=>.[TaUserService]); ta-user-service.spec.ts

  68. describe('TaUserService.Service',.().=>.{. ..beforeEachProviders(().=>.[TaUserService]);. ..describe('#getUser',.().=>.{. ....it('should.get.the.user',. ......inject([TaUserService],.fakeAsync((service:.TaUserService).=>.{. ......let.user;. ......service.getUser('cironunes').then((value).=>.{. ........user.=.value;. ......});. ......tick();.

    ......expect(user.age).toBe(24);. ......expect(user.favoriteColor).toBe('black');. ....}))); ta-user-service.spec.ts
  69. describe('TaUserService.Service',.().=>.{. ..beforeEachProviders(().=>.[TaUserService]);. ..describe('#getUser',.().=>.{. ....it('should.get.the.user',. ......inject([TaUserService],.fakeAsync((service:.TaUserService).=>.{. ......let.user;. ......service.getUser('cironunes').then((value).=>.{. ........user.=.value;. ......});. ......tick();.

    ......expect(user.age).toBe(24);. ......expect(user.favoriteColor).toBe('black');. ....}))); ta-user-service.spec.ts
  70. DEMO https://github.com/cironunes/ng2-tests

  71. SUMMARY

  72. 1. Unit tests helps us to test applications automatically SUMMARY

  73. 1. Unit tests helps us to test applications automatically 2.

    Good tests are small and test the public interface SUMMARY
  74. 1. Unit tests helps us to test applications automatically 2.

    Good tests are small and test the public interface 3. The CLI is the recommended way to get up and running SUMMARY
  75. 1. Unit tests helps us to test applications automatically 2.

    Good tests are small and test the public interface 3. The CLI is the recommended way to get up and running SUMMARY 4. The testing library wraps Jasmine and provide convenient features
  76. 1. Unit tests helps us to test applications automatically 2.

    Good tests are small and test the public interface 3. The CLI is the recommended way to get up and running SUMMARY 4. The testing library wraps Jasmine and provide convenient features 5. beforeEachProviders + inject/injectAsync to use the DI system
  77. 1. Unit tests helps us to test applications automatically 2.

    Good tests are small and test the public interface 3. The CLI is the recommended way to get up and running SUMMARY 4. The testing library wraps Jasmine and provide convenient features 5. beforeEachProviders + inject/injectAsync to use the DI system 6. provide to mock dependencies
  78. SUMMARY

  79. 7. TestComponentBuilder returns the ComponentFixture instance SUMMARY

  80. 7. TestComponentBuilder returns the ComponentFixture instance 8. The ComponentFixture contains

    the component instance SUMMARY
  81. 7. TestComponentBuilder returns the ComponentFixture instance 8. The ComponentFixture contains

    the component instance 9. The ComponentFixture contains the DOM element SUMMARY
  82. 7. TestComponentBuilder returns the ComponentFixture instance 8. The ComponentFixture contains

    the component instance 9. The ComponentFixture contains the DOM element SUMMARY 10. fakeAsync and tick to test async code in a sync fashion
  83. 7. TestComponentBuilder returns the ComponentFixture instance 8. The ComponentFixture contains

    the component instance 9. The ComponentFixture contains the DOM element SUMMARY 10. fakeAsync and tick to test async code in a sync fashion 11. injectAsync will be deprecated in favor of async
  84. 1. Pipes 2. HTTP 3. Observables What wasn’t covered

  85. THANK YOU! @cironunesdev http://cnun.es/a2-unit-testing