SlideShare a Scribd company logo
Software testing
with examples in Angular (and AngularJS)
2018-02-08Paweł Żurowski <zurowski.pawel@gmail.com>
Agenda
• it('should tell about me', ...)
• Experiment
• Discussion
• About testing (in general)
• Best practices
• Live coding: TDD
• How to deal with X?
• QA
Paweł Żurowski <zurowski.pawel@gmail.com> 2018-02-08
it('should tell about me', ...)
• I started programming 19 years ago
• I code for money from the 10 years
• I code for Decerto ~4 years
• I was programming in Pascal, C, PHP, Javascript, Bash, SQL, C++, Java,
Typescript
• I did some AJAX before it was popular
• I did some UX before it was so popular
• I did some Devops before it was so named
• I am doing TDD over the last 5 years (in AngularJS, Angular)
• I regret I have not use TDD before
Paweł Żurowski <zurowski.pawel@gmail.com> 2018-02-08
it('should tell about me', ...)
• I started programming 19 years ago
• I code for money from the 10 years
• I code for Decerto ~4 years
• I was programming in Pascal, C, PHP, Javascript, Bash, SQL, C++, Java,
Typescript
• I did some AJAX before it was popular
• I did some UX before it was so popular
• I did some Devops before it was so named
• I am doing TDD over the last 5 years (in AngularJS, Angular)
• I regret I have not use TDD before
Paweł Żurowski <zurowski.pawel@gmail.com> 2018-02-08
Let’s split up into to teams
• Quiz
• Mark each answer on the scoring sheet
• There is no wrong answer!
• Splitting conditions
•
•
•
•
• Each team designate a leader
Scoring sheet
Question: 1 2 3 4 5 6 7 total
I totally agree
I rather agree
I rather disagree
I totally disagree
I rarely use a debugger
•I totally agree
•I rather agree
•I rather disagree
•I totally disagree
I write more tests LOC than production LOC
•I totally agree
•I rather agree
•I rather disagree
•I totally disagree
I do test getters and setters
•I totally agree
•I rather agree
•I rather disagree
•I totally disagree
I am a professional programmer
•I totally agree
•I rather agree
•I rather disagree
•I totally disagree
I write buggy code
•I totally agree
•I rather agree
•I rather disagree
•I totally disagree
I am not afraid of refactoring
•I totally agree
•I rather agree
•I rather disagree
•I totally disagree
My code has 100% test coverage
•I totally agree
•I rather agree
•I rather disagree
•I totally disagree
Scoring sheet
Question: 1 2 3 4 5 6 7 total
I totally agree
I rather agree
I rather disagree
I totally disagree
Let’s split up into to teams
• Quiz
• Mark each answer on the scoring sheet
• There is no wrong answer!
• Splitting conditions
• Sum up your points - S
• Find the median of all results
• Team A – if score is less then median
• Team B – otherwise
• Each team designate a leader
Scoring sheet
Question: 1 2 3 4 5 6 7 total wage points
I totally agree 2
I rather agree 3
I rather disagree 5
I totally disagree 8
sum
Why are not we testing our own code?
Why are we do testing our own code?
Less then median
otherwise
Why are not we testing our own code?
• It’s too hard
• We don’t know how
• It’s unnecessary
• We don’t have time
• It’s too silly
• We have paid for the code
• It’s only for beginners
• We’ve a deadline
• It’s only for experts
• We don’t want to
• It’s too expensive
• We’re told not to do so
• It’s already working
• We’ve written not testable code
• It’s job for QA
• We’re not told we have to
• It’s boring
• We don’t err
Why are we do testing our own code?
Testing. Big or not?
Testing. Big or not? (from ISTQB Glossary)
acceptance testing, accessibility testing, accuracy testing, ad hoc testing, Agile testing, alpha testing, analytical testing, API
testing, attack-based testing, beta testing, big-bang testing, black-box testing, bottom-up testing, branch testing, business
process-based testing, checklist-based testing, CLI testing, combinatorial testing, compliance testing, component integration
testing, component testing, concurrency testing, condition testing, confirmation testing, consultative testing, control flow
testing, conversion testing, Critical Testing Processes, data flow testing, data-driven testing, database integrity testing,
decision condition testing, decision table testing, decision testing, design-based testing, development testing, discount
usability testing, documentation testing, dynamic testing, efficiency testing, elementary comparison testing, exhaustive
testing, experience-based testing, exploratory testing, factory acceptance testing, failover testing, functional testing,
functionality testing, fuzz testing, GUI testing, hardware-software integration testing, incremental testing, independence of
testing, insourced testing, installability testing, integration testing, interface testing, interoperability testing, invalid testing,
isolation testing, keyword-driven testing, load testing, load testing tool, maintainability testing, maintenance testing,
methodical testing, model-based testing, modified condition / decision testing, monkey testing, multiple condition testing,
mutation testing, N-switch testing, n-wise testing, negative testing, neighborhood integration testing, non-functional testing,
operational acceptance testing, operational profile testing, operational testing, orthogonal array testing, outsourced testing,
pair testing, pairwise integration testing, pairwise testing, path testing, penetration testing, performance testing,
performance testing tool, portability testing, procedure testing, process-compliant testing, random testing, reactive testing,
recoverability testing, regression testing, regression-averse testing, reliability testing, requirements-based testing, resource
utilization testing, risk-based testing, robustness testing, safety testing, scalability testing, scripted testing, security testing,
security testing tool, session-based testing, site acceptance testing, standard-compliant testing, state transition testing,
statement testing, static testing, statistical testing, stress testing, stress testing tool, suitability testing, syntax testing, system
integration testing, system testing, think aloud usability testing
Test type
UI
tests
Integration
tests
Unit tests
https://www.slideshare.net/erdemcp/endtoend-test-automation-for-both-horizontal-and-vertical-scale/19
High
Medium
Low
Long/High
Medium
Short/Low
Low
Medium
High
Business Logic
Coverage
Code
Coverage
Execution
Time/Costs
Test type
manual
tests
E2E tests
Tests with
testbed
Tests without
testbed
High
Medium
Low
Long/High
Medium
Short/Low
Low
Medium
High
Business Logic
Coverage
Code
Coverage
Execution
Time/Costs
AAA ?
AAA ??
Image source: https://commons.wikimedia.org/wiki/File:Three_AAA_Batteries_and_one_AA_Battery.JPG
AAA
• Arrange
• Act
• Assert
AAA
• Arrange
• Act
• Assert
• Given
• When
• Then
AAA
• Arrange
• Act
• Assert
describe('namesReducer', () => {
it('should sort', () => {
const inputState = {data: ['dd', 'aa', 'cc', 'bb']};
const state = namesReducer(inputState, {type: 'SORT'});
expect(state.data).toEqual(['aa', 'bb', 'cc', 'dd',]);
})
});
Best practices – AAA
• Why?
• Each stage has been separated
• It’s easy to add a trigger just after
the act statement
• You have 100% certainty that
assertion have been called
• Easy to spot preparation and
expectations
it('dont', () => {
something.method()
.then(result =>
expect(result).toEqual(42))
});
it('do',()=>{
let result = null;
something.method()
.then(aResult => result = aResult);
expect(result).toEqual(42);
});
Best practices – Less DRY
• Why?
• Too much DRY is consider harmful
• You are immune to nasty bugs
• act(x){ x.splice(0); return x; }
• You can still DRY with
beforeEach sections
it('dont', () => {
const DATA = [1, 1, 2, 3, 5, 8, 13];
const result = something.act(DATA);
expect(result).toEqual(DATA);
});
it('do',()=>{
const result = something.act(
[1, 1, 2, 3, 5, 8, 13]);
expect(result).toEqual(
[1, 1, 2, 3, 5, 8, 13]);
});
Best practices – check one thing at a time
• Why?
• If something blow up you will be
know what exactly
• There are no preconditions,
there are postcondition of
starting situations
• You can still use many
expectations as long as you
check the same one thing
it('dont', () => {
expect(something.here).toEqual(42);
something.act();
expect(something.here).toEqual(24);
});
it('do 1',()=>{
expect(something.here).toEqual(42);
});
it('do 2',()=>{
something.act();
expect(something.here).toEqual(24);
});
Best practices – group by common case
• Why?
• Easier to reason about
• Easier to write
• It looks like documentation
describe('stack',()=>{
describe('when empty',()=>{
it('should fail on pop');
it('should push element on top');
it('should have no elements');
});
describe('with one element',()=>{
it('should pop the element');
it('should push element on top');
it('should have 1 element');
});
describe('when full',()=>{
it('should pop the element');
it('should fail on push');
it('should have SIZE elements');
});
});
Best practices – Test Driven Development
Uncle Bob
Rules:
• You are not allowed to write any
production code unless it is to make a
failing unit test pass.
• You are not allowed to write any
more of a unit test than is sufficient
to fail; and compilation failures are
failures.
• You are not allowed to write any
more production code than is
sufficient to pass the one failing unit
test.
Kent Beck
Rules:
• Don’t write a line of new code unless you
first have a failing automated test.
• Eliminate duplication
Tasks:
• Red—write a little test that doesn’t work,
perhaps doesn’t even compile at first
• Green—make the test work quickly,
committing whatever sins necessary in
the process
• Refactor—eliminate all the duplication
created in just getting the test to work
Best practices – Test Driven Development
Uncle Bob
(…) think about what would happen if
you walked in a room full of people
working this way. Pick any random
person at any random time. A minute
ago, all their code worked.
Let me repeat that: A minute ago all
their code worked! And it doesn't
matter who you pick, and it doesn't
matter when you pick. A minute ago all
their code worked!
Kent Beck
The general TDD cycle goes as follows.
1. Write a test…
2. Make it run…
3. Make it right…
The goal is clean code that works
(thanks to Ron Jeffries for this pithy
summary)… First we’ll solve the “that
works” part of the problem. Then we’ll
solve the “clean code” part.
Live coding – TDD
How to deal with services?
spyOn(SomeResource, 'save')
.and.returnValue({$promise: $q.when({})});
$cookies = jasmine.createSpyObj('$cookies', ['put', 'get']);
someServiceMock = jasmine.createSpyObj(‚someService',
Object.keys(SomeService.prototype));
How to deal with components?
beforeEach(inject(function ($componentController) {
ctrl = $componentController('aComponent',
{
overrideDI: something
},
{
binding: 42
});
ctrl.$onInit();
}));
afterEach(function () {
ctrl.$onDestroy();
});
How to deal with date?
beforeEach(() => {
jasmine.clock().install();
});
afterEach(() => {
jasmine.clock().uninstall();
});
it('should do something on leap day', () => {
jasmine.clock().mockDate(new Date(2020, 1, 29));
const result = something.doIt();
expect(result).toEqual(42);
});
How to deal with global object? (1)
describe('TheService', () => {
let service: RoutingService;
// ...
it('should navigate outside the app', () => {
service.openExternal('www.decerto.pl');
expect(window.open).toHaveBeenCalledWith('https://www.decerto.pl');
});
});
How to deal with global object? (2)
describe('TheService', () => {
let service: TheService;
let window: Window;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [TheService,
{provide: windowToken, useValue: {open: createSpy('open')}}
],
});
service = TestBed.get(TheService);
window = TestBed.get(windowToken);
});
// ...
});
How to deal with global object? (3)
export const windowToken = new InjectionToken<Window>('Window token');
// ------------------------------------------------
@Injectable()
export class TheService {
constructor(@Inject(windowToken) private window: Window) {
}
openExternal(url: string) {
this.window.open(`https://${url}`);
}
}
{provide: windowToken, useValue: window}
How to deal with data service? (1)
@Injectable()
export abstract class SthDataService {
abstract create(): Observable<Sth>;
abstract fetch(sthId: string): Observable<Sth>;
}
@Injectable()
export class SthDataServiceImpl implements SthDataService {
constructor(private http: HttpClient,
@Inject(apiUrlToken) private api: string) {
}
create(): Observable<Sth> {
return this.http.post<Sth>(`${this.api}sth`, {x: 42});
}
fetch(sthId: string): Observable<Sth> {
return this.http.get<Sth>(`${this.api}sth/${sthId}`);
}
}
How to deal with data service? (2)
describe('SthDataService', () => {
let service: SthDataService;
let httpMock: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
{provice: SthDataService, useClass: SthDataServiceImpl},
{provide: apiUrlToken, useValue: API},
]
});
service = TestBed.get(SthDataService);
httpMock = TestBed.get(HttpTestingController);
});
How to deal with data service? (3)
afterEach(() => httpMock.verify());
it('should fetch sth', () => {
const result = [];
service.fetch('xyz').subscribe(item => result.push(item));
const req = httpMock.expectOne(`${API}sth/xyz`);
req.flush(sampleSthById('xyz'));
expect(req.request.method).toBe('GET');
expect(req.request.url).toBe(`${API}sth/xyz`);
expect(result).toEqual([
sampleSthById('xyz'),
]);
});
How to deal with data service? (4)
@Injectable()
export class SthDataServiceMock implements SthDataService {
constructor(@Optional() private testScheduler: Scheduler,
@Inject(apiMockDelayToken) private delayMs: DelayMs) {}
private get scheduler() {
return this.testScheduler ? this.testScheduler :
/* istanbul ignore next: Scheduler to use when mocking
backend outside the tests */ async;
}
create(): Observable<Sth> {
return this.toDelayedObservable(sampleSthById('new'));
}
fetch(sthId: string): Observable<Sth> {
return this.toDelayedObservable(sampleSthById(sthId));
}
How to deal with data service? (5)
private toDelayedObservable<T>(value: T): Observable<T> {
return interval(this.delayMs(), this.scheduler).pipe(
take(1),
mapTo(value),
);
}
export type DelayMs = () => number;
export const apiUrlToken = new InjectionToken<string>('Api url prefix');
export const apiMockDelayToken = new InjectionToken<DelayMs>('Delay fn');
export const apiMockDelayProvider = (min = 500, max = 2000): Provider[] => [
{
provide: apiMockDelayToken,
useValue: () => min + Math.round(Math.random() * (max - min))
}];
How to deal with observables?
it('should fetch document when requested one mismatch actual', () => {
(serviceMock.selectDoc as Spy)
.and.returnValue(new BehaviorSubject({id: 'doc'}));
const actions = new Actions(hot('--a----b----b-c---', {
a: {type: ActionTypes.REQUEST_DOCUMENT, docId: 'doc'},
b: {type: ActionTypes.REQUEST_DOCUMENT, docId: 'sth'},
c: {type: ActionTypes.REQUEST_DOCUMENT, docId: 'other'},
}));
const effects = createEffects(actions);
expect(effects.fetch$).toBeObservable(hot('----------B------C-', {
B: {type: ActionTypes.DOCUMENT, doc: sampleDocById('sth')},
C: {type: ActionTypes.DOCUMENT, doc: sampleDocById('other')},
}));
});
How to deal with effects? (without Testbed)
let storeMock: Store<{ something: SomethingState }>;
let stateSubject: BehaviorSubject<{ something: SomethingState }>;
function createEffects(actions: Actions<Action>) {
return new SomethingEffects(actions,
new SomethingService(storeMock),
new SomethingDataServiceMock(getTestScheduler(), () => 30));
}
beforeEach(() => {
stateSubject = new BehaviorSubject({});
storeMock = this.stateSubject.asObservable();
});
Software testing with examples in Angular (and AngularJS)
Q&A.

More Related Content

PPTX
Writing acceptable patches: an empirical study of open source project patches
PDF
Clean tests
PDF
Iakiv Kramarenko: “Quality Driven Development”
PPTX
Improving the Quality of Existing Software - DevIntersection April 2016
PPTX
Improving The Quality of Existing Software
PPTX
Improving the Quality of Existing Software
PPTX
Anatomy of Test Driven Development
PPTX
Improving the Quality of Existing Software
Writing acceptable patches: an empirical study of open source project patches
Clean tests
Iakiv Kramarenko: “Quality Driven Development”
Improving the Quality of Existing Software - DevIntersection April 2016
Improving The Quality of Existing Software
Improving the Quality of Existing Software
Anatomy of Test Driven Development
Improving the Quality of Existing Software

What's hot (20)

PPTX
Approval Tests in Action: A LEGO Exercise and an Experience Report
PDF
Selenium Users Anonymous
PPTX
Working Effectively With Legacy Code
PDF
Exploratory Testing Basics, Experiences, and Future in SSTC2016
PPSX
Test analysis & design good practices@TDT Iasi 17Oct2013
PPSX
GLA Testing Presentation by Test Partners Ltd v1
PPTX
Improving the Quality of Existing Software
PDF
QA / Testing Tools, Automation Testing, Online & Classroom Training
PDF
Exploratory testing Kari Kakkonen KDS2015
PPTX
QA Club Kiev #17 Measuring quality by Volodymyr Prymakov
PPTX
Breaking Dependencies to Allow Unit Testing
PPTX
Automated Software Testing
PDF
Continuous Security Testing
PDF
Adopting tdd in the workplace
PDF
Adopting technical practices 2013
PPTX
Agile testing for mere mortals
PPTX
Clean code - Getting your R&D on board
PPTX
Inspection used in various ways
PPTX
10 signs your testing is not enough
PDF
Behavior Driven Development—A Guide to Agile Practices by Josh Eastman
Approval Tests in Action: A LEGO Exercise and an Experience Report
Selenium Users Anonymous
Working Effectively With Legacy Code
Exploratory Testing Basics, Experiences, and Future in SSTC2016
Test analysis & design good practices@TDT Iasi 17Oct2013
GLA Testing Presentation by Test Partners Ltd v1
Improving the Quality of Existing Software
QA / Testing Tools, Automation Testing, Online & Classroom Training
Exploratory testing Kari Kakkonen KDS2015
QA Club Kiev #17 Measuring quality by Volodymyr Prymakov
Breaking Dependencies to Allow Unit Testing
Automated Software Testing
Continuous Security Testing
Adopting tdd in the workplace
Adopting technical practices 2013
Agile testing for mere mortals
Clean code - Getting your R&D on board
Inspection used in various ways
10 signs your testing is not enough
Behavior Driven Development—A Guide to Agile Practices by Josh Eastman
Ad

Similar to Software testing with examples in Angular (and AngularJS) (20)

PDF
Lessons Learned When Automating
PPTX
Why Automated Testing Matters To DevOps
KEY
Beyond TDD: Enabling Your Team to Continuously Deliver Software
PPTX
Unit Testing and TDD 2017
PPTX
Sustainable agile testing
KEY
Driving application development through behavior driven development
KEY
Unit Test Your Database
PPTX
Introduction to Testing and TDD
PDF
Jest: Frontend Testing richtig gemacht @WebworkerNRW
PPTX
Introduction to Test Driven Development
PDF
Developer Tests - Things to Know
PDF
Das Frontend richtig Testen – mit Jest @Developer Week 2018
PPTX
Testable requirements
PPT
Tester career path
PPTX
New model
PPTX
A New Model For Testing
PDF
Start with passing tests (tdd for bugs) v0.5 (22 sep 2016)
PDF
How to use selenium successfully
KEY
Introduction to atdd
PDF
Agile testing
Lessons Learned When Automating
Why Automated Testing Matters To DevOps
Beyond TDD: Enabling Your Team to Continuously Deliver Software
Unit Testing and TDD 2017
Sustainable agile testing
Driving application development through behavior driven development
Unit Test Your Database
Introduction to Testing and TDD
Jest: Frontend Testing richtig gemacht @WebworkerNRW
Introduction to Test Driven Development
Developer Tests - Things to Know
Das Frontend richtig Testen – mit Jest @Developer Week 2018
Testable requirements
Tester career path
New model
A New Model For Testing
Start with passing tests (tdd for bugs) v0.5 (22 sep 2016)
How to use selenium successfully
Introduction to atdd
Agile testing
Ad

Recently uploaded (20)

PDF
Softaken Excel to vCard Converter Software.pdf
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
How Creative Agencies Leverage Project Management Software.pdf
PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PPTX
Reimagine Home Health with the Power of Agentic AI​
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
Design an Analysis of Algorithms II-SECS-1021-03
PPTX
Odoo POS Development Services by CandidRoot Solutions
PDF
wealthsignaloriginal-com-DS-text-... (1).pdf
PDF
System and Network Administraation Chapter 3
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PPTX
history of c programming in notes for students .pptx
PDF
top salesforce developer skills in 2025.pdf
Softaken Excel to vCard Converter Software.pdf
Operating system designcfffgfgggggggvggggggggg
How Creative Agencies Leverage Project Management Software.pdf
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
Reimagine Home Health with the Power of Agentic AI​
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
How to Migrate SBCGlobal Email to Yahoo Easily
How to Choose the Right IT Partner for Your Business in Malaysia
Design an Analysis of Algorithms I-SECS-1021-03
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
Which alternative to Crystal Reports is best for small or large businesses.pdf
VVF-Customer-Presentation2025-Ver1.9.pptx
CHAPTER 2 - PM Management and IT Context
Design an Analysis of Algorithms II-SECS-1021-03
Odoo POS Development Services by CandidRoot Solutions
wealthsignaloriginal-com-DS-text-... (1).pdf
System and Network Administraation Chapter 3
Adobe Illustrator 28.6 Crack My Vision of Vector Design
history of c programming in notes for students .pptx
top salesforce developer skills in 2025.pdf

Software testing with examples in Angular (and AngularJS)

  • 1. Software testing with examples in Angular (and AngularJS) 2018-02-08Paweł Żurowski <zurowski.pawel@gmail.com>
  • 2. Agenda • it('should tell about me', ...) • Experiment • Discussion • About testing (in general) • Best practices • Live coding: TDD • How to deal with X? • QA Paweł Żurowski <zurowski.pawel@gmail.com> 2018-02-08
  • 3. it('should tell about me', ...) • I started programming 19 years ago • I code for money from the 10 years • I code for Decerto ~4 years • I was programming in Pascal, C, PHP, Javascript, Bash, SQL, C++, Java, Typescript • I did some AJAX before it was popular • I did some UX before it was so popular • I did some Devops before it was so named • I am doing TDD over the last 5 years (in AngularJS, Angular) • I regret I have not use TDD before Paweł Żurowski <zurowski.pawel@gmail.com> 2018-02-08
  • 4. it('should tell about me', ...) • I started programming 19 years ago • I code for money from the 10 years • I code for Decerto ~4 years • I was programming in Pascal, C, PHP, Javascript, Bash, SQL, C++, Java, Typescript • I did some AJAX before it was popular • I did some UX before it was so popular • I did some Devops before it was so named • I am doing TDD over the last 5 years (in AngularJS, Angular) • I regret I have not use TDD before Paweł Żurowski <zurowski.pawel@gmail.com> 2018-02-08
  • 5. Let’s split up into to teams • Quiz • Mark each answer on the scoring sheet • There is no wrong answer! • Splitting conditions • • • • • Each team designate a leader
  • 6. Scoring sheet Question: 1 2 3 4 5 6 7 total I totally agree I rather agree I rather disagree I totally disagree
  • 7. I rarely use a debugger •I totally agree •I rather agree •I rather disagree •I totally disagree
  • 8. I write more tests LOC than production LOC •I totally agree •I rather agree •I rather disagree •I totally disagree
  • 9. I do test getters and setters •I totally agree •I rather agree •I rather disagree •I totally disagree
  • 10. I am a professional programmer •I totally agree •I rather agree •I rather disagree •I totally disagree
  • 11. I write buggy code •I totally agree •I rather agree •I rather disagree •I totally disagree
  • 12. I am not afraid of refactoring •I totally agree •I rather agree •I rather disagree •I totally disagree
  • 13. My code has 100% test coverage •I totally agree •I rather agree •I rather disagree •I totally disagree
  • 14. Scoring sheet Question: 1 2 3 4 5 6 7 total I totally agree I rather agree I rather disagree I totally disagree
  • 15. Let’s split up into to teams • Quiz • Mark each answer on the scoring sheet • There is no wrong answer! • Splitting conditions • Sum up your points - S • Find the median of all results • Team A – if score is less then median • Team B – otherwise • Each team designate a leader
  • 16. Scoring sheet Question: 1 2 3 4 5 6 7 total wage points I totally agree 2 I rather agree 3 I rather disagree 5 I totally disagree 8 sum
  • 17. Why are not we testing our own code? Why are we do testing our own code? Less then median otherwise
  • 18. Why are not we testing our own code? • It’s too hard • We don’t know how • It’s unnecessary • We don’t have time • It’s too silly • We have paid for the code • It’s only for beginners • We’ve a deadline • It’s only for experts • We don’t want to • It’s too expensive • We’re told not to do so • It’s already working • We’ve written not testable code • It’s job for QA • We’re not told we have to • It’s boring • We don’t err
  • 19. Why are we do testing our own code?
  • 21. Testing. Big or not? (from ISTQB Glossary) acceptance testing, accessibility testing, accuracy testing, ad hoc testing, Agile testing, alpha testing, analytical testing, API testing, attack-based testing, beta testing, big-bang testing, black-box testing, bottom-up testing, branch testing, business process-based testing, checklist-based testing, CLI testing, combinatorial testing, compliance testing, component integration testing, component testing, concurrency testing, condition testing, confirmation testing, consultative testing, control flow testing, conversion testing, Critical Testing Processes, data flow testing, data-driven testing, database integrity testing, decision condition testing, decision table testing, decision testing, design-based testing, development testing, discount usability testing, documentation testing, dynamic testing, efficiency testing, elementary comparison testing, exhaustive testing, experience-based testing, exploratory testing, factory acceptance testing, failover testing, functional testing, functionality testing, fuzz testing, GUI testing, hardware-software integration testing, incremental testing, independence of testing, insourced testing, installability testing, integration testing, interface testing, interoperability testing, invalid testing, isolation testing, keyword-driven testing, load testing, load testing tool, maintainability testing, maintenance testing, methodical testing, model-based testing, modified condition / decision testing, monkey testing, multiple condition testing, mutation testing, N-switch testing, n-wise testing, negative testing, neighborhood integration testing, non-functional testing, operational acceptance testing, operational profile testing, operational testing, orthogonal array testing, outsourced testing, pair testing, pairwise integration testing, pairwise testing, path testing, penetration testing, performance testing, performance testing tool, portability testing, procedure testing, process-compliant testing, random testing, reactive testing, recoverability testing, regression testing, regression-averse testing, reliability testing, requirements-based testing, resource utilization testing, risk-based testing, robustness testing, safety testing, scalability testing, scripted testing, security testing, security testing tool, session-based testing, site acceptance testing, standard-compliant testing, state transition testing, statement testing, static testing, statistical testing, stress testing, stress testing tool, suitability testing, syntax testing, system integration testing, system testing, think aloud usability testing
  • 23. Test type manual tests E2E tests Tests with testbed Tests without testbed High Medium Low Long/High Medium Short/Low Low Medium High Business Logic Coverage Code Coverage Execution Time/Costs
  • 24. AAA ?
  • 25. AAA ?? Image source: https://commons.wikimedia.org/wiki/File:Three_AAA_Batteries_and_one_AA_Battery.JPG
  • 27. AAA • Arrange • Act • Assert • Given • When • Then
  • 28. AAA • Arrange • Act • Assert describe('namesReducer', () => { it('should sort', () => { const inputState = {data: ['dd', 'aa', 'cc', 'bb']}; const state = namesReducer(inputState, {type: 'SORT'}); expect(state.data).toEqual(['aa', 'bb', 'cc', 'dd',]); }) });
  • 29. Best practices – AAA • Why? • Each stage has been separated • It’s easy to add a trigger just after the act statement • You have 100% certainty that assertion have been called • Easy to spot preparation and expectations it('dont', () => { something.method() .then(result => expect(result).toEqual(42)) }); it('do',()=>{ let result = null; something.method() .then(aResult => result = aResult); expect(result).toEqual(42); });
  • 30. Best practices – Less DRY • Why? • Too much DRY is consider harmful • You are immune to nasty bugs • act(x){ x.splice(0); return x; } • You can still DRY with beforeEach sections it('dont', () => { const DATA = [1, 1, 2, 3, 5, 8, 13]; const result = something.act(DATA); expect(result).toEqual(DATA); }); it('do',()=>{ const result = something.act( [1, 1, 2, 3, 5, 8, 13]); expect(result).toEqual( [1, 1, 2, 3, 5, 8, 13]); });
  • 31. Best practices – check one thing at a time • Why? • If something blow up you will be know what exactly • There are no preconditions, there are postcondition of starting situations • You can still use many expectations as long as you check the same one thing it('dont', () => { expect(something.here).toEqual(42); something.act(); expect(something.here).toEqual(24); }); it('do 1',()=>{ expect(something.here).toEqual(42); }); it('do 2',()=>{ something.act(); expect(something.here).toEqual(24); });
  • 32. Best practices – group by common case • Why? • Easier to reason about • Easier to write • It looks like documentation describe('stack',()=>{ describe('when empty',()=>{ it('should fail on pop'); it('should push element on top'); it('should have no elements'); }); describe('with one element',()=>{ it('should pop the element'); it('should push element on top'); it('should have 1 element'); }); describe('when full',()=>{ it('should pop the element'); it('should fail on push'); it('should have SIZE elements'); }); });
  • 33. Best practices – Test Driven Development Uncle Bob Rules: • You are not allowed to write any production code unless it is to make a failing unit test pass. • You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures. • You are not allowed to write any more production code than is sufficient to pass the one failing unit test. Kent Beck Rules: • Don’t write a line of new code unless you first have a failing automated test. • Eliminate duplication Tasks: • Red—write a little test that doesn’t work, perhaps doesn’t even compile at first • Green—make the test work quickly, committing whatever sins necessary in the process • Refactor—eliminate all the duplication created in just getting the test to work
  • 34. Best practices – Test Driven Development Uncle Bob (…) think about what would happen if you walked in a room full of people working this way. Pick any random person at any random time. A minute ago, all their code worked. Let me repeat that: A minute ago all their code worked! And it doesn't matter who you pick, and it doesn't matter when you pick. A minute ago all their code worked! Kent Beck The general TDD cycle goes as follows. 1. Write a test… 2. Make it run… 3. Make it right… The goal is clean code that works (thanks to Ron Jeffries for this pithy summary)… First we’ll solve the “that works” part of the problem. Then we’ll solve the “clean code” part.
  • 36. How to deal with services? spyOn(SomeResource, 'save') .and.returnValue({$promise: $q.when({})}); $cookies = jasmine.createSpyObj('$cookies', ['put', 'get']); someServiceMock = jasmine.createSpyObj(‚someService', Object.keys(SomeService.prototype));
  • 37. How to deal with components? beforeEach(inject(function ($componentController) { ctrl = $componentController('aComponent', { overrideDI: something }, { binding: 42 }); ctrl.$onInit(); })); afterEach(function () { ctrl.$onDestroy(); });
  • 38. How to deal with date? beforeEach(() => { jasmine.clock().install(); }); afterEach(() => { jasmine.clock().uninstall(); }); it('should do something on leap day', () => { jasmine.clock().mockDate(new Date(2020, 1, 29)); const result = something.doIt(); expect(result).toEqual(42); });
  • 39. How to deal with global object? (1) describe('TheService', () => { let service: RoutingService; // ... it('should navigate outside the app', () => { service.openExternal('www.decerto.pl'); expect(window.open).toHaveBeenCalledWith('https://www.decerto.pl'); }); });
  • 40. How to deal with global object? (2) describe('TheService', () => { let service: TheService; let window: Window; beforeEach(() => { TestBed.configureTestingModule({ providers: [TheService, {provide: windowToken, useValue: {open: createSpy('open')}} ], }); service = TestBed.get(TheService); window = TestBed.get(windowToken); }); // ... });
  • 41. How to deal with global object? (3) export const windowToken = new InjectionToken<Window>('Window token'); // ------------------------------------------------ @Injectable() export class TheService { constructor(@Inject(windowToken) private window: Window) { } openExternal(url: string) { this.window.open(`https://${url}`); } } {provide: windowToken, useValue: window}
  • 42. How to deal with data service? (1) @Injectable() export abstract class SthDataService { abstract create(): Observable<Sth>; abstract fetch(sthId: string): Observable<Sth>; } @Injectable() export class SthDataServiceImpl implements SthDataService { constructor(private http: HttpClient, @Inject(apiUrlToken) private api: string) { } create(): Observable<Sth> { return this.http.post<Sth>(`${this.api}sth`, {x: 42}); } fetch(sthId: string): Observable<Sth> { return this.http.get<Sth>(`${this.api}sth/${sthId}`); } }
  • 43. How to deal with data service? (2) describe('SthDataService', () => { let service: SthDataService; let httpMock: HttpTestingController; beforeEach(() => { TestBed.configureTestingModule({ imports: [HttpClientTestingModule], providers: [ {provice: SthDataService, useClass: SthDataServiceImpl}, {provide: apiUrlToken, useValue: API}, ] }); service = TestBed.get(SthDataService); httpMock = TestBed.get(HttpTestingController); });
  • 44. How to deal with data service? (3) afterEach(() => httpMock.verify()); it('should fetch sth', () => { const result = []; service.fetch('xyz').subscribe(item => result.push(item)); const req = httpMock.expectOne(`${API}sth/xyz`); req.flush(sampleSthById('xyz')); expect(req.request.method).toBe('GET'); expect(req.request.url).toBe(`${API}sth/xyz`); expect(result).toEqual([ sampleSthById('xyz'), ]); });
  • 45. How to deal with data service? (4) @Injectable() export class SthDataServiceMock implements SthDataService { constructor(@Optional() private testScheduler: Scheduler, @Inject(apiMockDelayToken) private delayMs: DelayMs) {} private get scheduler() { return this.testScheduler ? this.testScheduler : /* istanbul ignore next: Scheduler to use when mocking backend outside the tests */ async; } create(): Observable<Sth> { return this.toDelayedObservable(sampleSthById('new')); } fetch(sthId: string): Observable<Sth> { return this.toDelayedObservable(sampleSthById(sthId)); }
  • 46. How to deal with data service? (5) private toDelayedObservable<T>(value: T): Observable<T> { return interval(this.delayMs(), this.scheduler).pipe( take(1), mapTo(value), ); } export type DelayMs = () => number; export const apiUrlToken = new InjectionToken<string>('Api url prefix'); export const apiMockDelayToken = new InjectionToken<DelayMs>('Delay fn'); export const apiMockDelayProvider = (min = 500, max = 2000): Provider[] => [ { provide: apiMockDelayToken, useValue: () => min + Math.round(Math.random() * (max - min)) }];
  • 47. How to deal with observables? it('should fetch document when requested one mismatch actual', () => { (serviceMock.selectDoc as Spy) .and.returnValue(new BehaviorSubject({id: 'doc'})); const actions = new Actions(hot('--a----b----b-c---', { a: {type: ActionTypes.REQUEST_DOCUMENT, docId: 'doc'}, b: {type: ActionTypes.REQUEST_DOCUMENT, docId: 'sth'}, c: {type: ActionTypes.REQUEST_DOCUMENT, docId: 'other'}, })); const effects = createEffects(actions); expect(effects.fetch$).toBeObservable(hot('----------B------C-', { B: {type: ActionTypes.DOCUMENT, doc: sampleDocById('sth')}, C: {type: ActionTypes.DOCUMENT, doc: sampleDocById('other')}, })); });
  • 48. How to deal with effects? (without Testbed) let storeMock: Store<{ something: SomethingState }>; let stateSubject: BehaviorSubject<{ something: SomethingState }>; function createEffects(actions: Actions<Action>) { return new SomethingEffects(actions, new SomethingService(storeMock), new SomethingDataServiceMock(getTestScheduler(), () => 30)); } beforeEach(() => { stateSubject = new BehaviorSubject({}); storeMock = this.stateSubject.asObservable(); });
  • 50. Q&A.