writing useful automated tests for the single page applications you build

Download Writing useful automated tests for the single page applications you build

If you can't read please download the document

Upload: andrei-sebastian-cimpean

Post on 15-Apr-2017

82 views

Category:

Software


0 download

TRANSCRIPT

Click to edit Master title style

4/12/17

Intreab cu ridicare de mn ci sunt developer i ci sunt QA

Writing useful automated tests for the Single Page Applications you build

Andrei Sebastian Cmpean, 2017@Andrei_Cimpean

A talk about
things I do to improve feedback

Big JS Frameworks ~2017

Work with a CLI

Have a preferred testing solution

Maximize render performance

Minimize boot time

Components and unidirectional data flow

Things are directly coupled to a multitude of things

Any change to one member, regardless of how trivial, will likely cause many others to require change

Fragile codebase

Where gut feeling worksShitty code

Benefits that come with tests

Easier ramp-up for newcomers on the project or feature

Code reuse is encouraged

Developer uses the code as a client would

Automated testing

Isnt always simple

It's not always clear how to break a problem into small, testable units

Code that is more dependent on interaction than logic can be hard to write tests for

Testing is hard when tests are slow

Every programmer knows they should write tests for their code. Few do.

Noel Rappin Journal 2

Writing automated tests

Writing automated tests for the ~2017 Single Page Apps

Writing useful automated tests for the ~2017 Single Page Apps

Writing useful automated tests for the Single Page Applications you build

Types of tests

That check state

That check behavior

There are other ways of separating tests by type, but well focus only on this one

State verification

Describes a style of testing where you exercise one or many methods of an object and then assert the expected state of the object (and/or collaborators).

Movie movie = a.movie.build();Rental rental = a.rental.w(movie).build();Store store = a.store.w(movie).build();rental.start(store);assertTrue(rental.isStarted());assertEquals(
0, store.getAvailability(movie)
);

State verification tests specify the least possible implementation detail, thus they will continue to pass even if the internals of the methods being tested are changed.

Behavior verification

Describes a style of testing where the execution of a method is expected to generate specific interactions between objects.

Movie movie = a.movie.build();Rental rental = a.rental.w(movie).build();Store store = mock(Store.class);when(store.getAvailability(movie)) .thenReturn(1);rental.start(store);assertTrue(rental.isStarted());

Behavior verification tests with minimal collaborators can effectively verify interactions without sacrificing maintainability.

Law of Demeter
Only talk to your immediate friends

Tell, Dont Ask
Rather than asking an object for data and acting on that data, we should instead tell an object what to do

A team that relies on Behavior verification will likely produce a codebase with few Law of Demeter violations and a focus on Tell, Dont Ask.

The canonical
testing tools:
test doubles,
unit and
acceptance
tests

Test doublesFake objects have incomplete/wrong working implementations

Stubs provide canned answers to calls made during the test

Spies are stubs that also record some information based on how they were called

Mocks are pre-programmed with expectations which form a specification of the calls they are expected to receive.

https://martinfowler.com/bliki/TestDouble.html

Acceptance testingperformed to verify that the product is acceptable to the customer and if it's fulfilling the specified requirements

Unit testingit tests a unit of the program as a whole

Acceptance tests

A test conducted to determine if the requirements of a specification or contract are met

from http://gregbabiars.com/acceptance-testing-a-react-app-using-react-test-utils-pretender-and-rxjs/

Acceptance tests

A test conducted to determine if the requirements of a specification or contract are met

Usually very slow to run

Theres usually a strategy put in place for when to run them

Unit tests

Low-level, focusing on a small part of the software system

From http://learnrubythehardway.org/book/ex47.html

Unit tests

Low-level, focusing on a small part of the software system

Significantly faster than other kinds of tests

Can be run very frequently when programming

Do
Public methods are a contract.
APIs should be tested.

Do
Its OK to write temporary tests for private methods. Implementation details is subject to change.

Enter
components

Components and unidirectional dataflow

Data down - Actions up

Presentational ContainerBusiness vs. Toolkit

Clear state management

Components make it obvious whats public and whats private

Props/Attributes are public

Everything else is private

Unit test

According to the definition on wikipedia a unit can be an individual method, but it can also be something much larger that likely includes many collaborating classes.Unit testing is an umbrella name for testing at a certain level of abstraction.

Integration testingbetween unit and acceptance testing

test the rendered state of a component (or nested group of components) in isolation from the rest of the app

Enter - Integration Testing

Integration tests

How components behave in regard to DOM Changes

Events

Async

Can be run very frequently when programming

Testing at the right level of abstraction for SPAs

Integration testsare cheap today

Modern JS frameworks Very fast rendering

Fast boot

start fast, remain fast

Powerful machines

From https://www.mutuallyhuman.com/blog/2016/01/22/component-integration-testing-in-ember

Do
Focus on writing integration tests for your components.

Do
Unit tests (for methods) are the exception. Write them only when they add substantially to confidence.

Templates change a lot

Design changes

Business

Mistake

Bug fixes

This will crash even though the logic didnt.

Do
Avoid matching for class names in integration tests.

Improve your setup!

Automatically cleans the HTML of test tags

Ideally not only used in templatesIf you need to check private attributes

ember-test-selectorsOr alternative for your framework of choice

Template file

Test file

What about methods?

Stop writing method tests that focus on parametersIf you can, and want to, use Typescript or Flow

Alternative, use inline assertions

Stop writing method tests that focus on parametersIf you can, and want to, use Typescript or Flow

Alternative, use inline assertions

Ember.assert('Test for truthiness', obj);Ember.assert('Fail unconditionally');

* In a production build, this method is defined as an empty function (NOP). Uses of this method in Ember itself are stripped from the ember.prod.js build

Inline asserts for rapid feedback

Ember.assert

Use it in appropriate placesLifecycle hooks when new required properties are set

Critical / fragile places

throw new ErrorClean up when building for production

Do
Write integration tests that the component is rendered correctly in all the contexts.

Do
Write integration tests that all actions are emitted correctly.

Things developers
say

Its not worth it and Im testing my code before I push to ...Its slowing me down...It wasnt done from the start of the project...The client doesnt pay for itWe have QA

Things developers
say

Its not worth it and Im testing my code before I push to ...Its slowing me down...It wasnt done from the start of the project...The client doesnt pay for itWe have QA ...ITS HARDNOT SOMETHING I USUALLY DO

Gut feeling and bias

Writing tests is slow

Not paid to write tests

Youre not paid to write tests, you just write enough to be confident that your code works as required. Refactoring without having tests is not refactoring, its moving code around.

Not paid to write tests

If I dont typically make a kind of mistake (like setting the wrong variables in a constructor), I dont test for it. I do tend to make sense of test errors, so Im extra careful when I have logic with complicated conditionals.When coding on a team, I modify my strategy to carefully test code that we, collectively, tend to get wrong.https://istacee.wordpress.com/2013/09/18/kent-beck-i-get-paid-for-code-that-works-not-for-tests/

You don't have enough tests (or good enough tests) if you can't confidently change the code.

Do
Evaluate what you and your team get out of tests and dont be afraid to tweak things around.

Do
Tests are part of the system and they must be maintained to the same standards as any other part of the system.

TESTS GIVECONFIDENCE

You don't have enough tests (or good enough tests) if you can't confidently change the code.

If you have a lot of tests, a single change to the production code can cause hundreds of tests to require corresponding changes. For example, if you add an argument to a method, every test that calls that method must be changed to add the new argument.

Fragile Test Problem

Fragile Test Problem:As the number of tests grows, a single change to the production code can cause hundreds of tests to require corresponding changes (add an argument to a method, every test must be changed )

SOLID PRINCIPLES

A one-to-one correspondence between production and test code implies extremely tight coupling.

If the structure of the tests follows the structure of the production code, then the tests are inextricably coupled to the production code

Test and production code evolve in opposite directions.

As the tests get more specific, the production code gets more generic.

http://blog.cleancoder.com/uncle-bob/2017/03/03/TDD-Harms-Architecture.html?__s=5sgof5whdhfhhnfby3e4

These two streams of code evolve in opposite directions. Programmers refactor tests to become more and more concrete and specific. They refactor the production code to become more and more abstract and general.

highly specific code cannot have a one-to-one correspondence with highly generic code

A test suite that isnt run regularly doesnt have many opportunities to provide positive ROI.

Do
Write a small test, make it pass.

Do
Write in small test/code cycles

Recap

Write in small cycles

Write integration tests for components

Minimize DOM dependency in tests

Only test what makes sense

Refactor tests

Dont pretend you can refactor without tests

Q & A

Would you rather throw away the code and keep the tests or vice-versa?How do you know if your code-base is healthy?

Mocks Arent Stubs, Martin FowlerUnitTest, Martin FowlerIs TDD dead?, Kent Beck, David Heinemeier Hansson, Martin FowlerTDD Harms Architecture, Rober C. Martin"Working Effectively With Unit Tests", Jay FieldsTest Driven Development