0% found this document useful (0 votes)
8 views16 pages

Unit Test Presentation

Written guide for a corporative presentation and team training to use unit test on Angular apps

Uploaded by

victor.portazio
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views16 pages

Unit Test Presentation

Written guide for a corporative presentation and team training to use unit test on Angular apps

Uploaded by

victor.portazio
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 16

Automated app testing

What is this? A legendary Pokémon?


Automated testing is a core feature available in every project set up with the Angular CLI.
Testing your Angular application helps you check that your application is working as you
expect.

It helps catch errors before releasing. It’s not bug free as the automated testings are
programmer-directed, but assures a greater quality of code.

But… my app is working properly!


Automated testing does not replace the manual testing, but as an application grows
complexity and more features are added to the project, the automated testing guarantees
the plain functioning of the application - at least, prevents crashing and
syntax/imports/interface errors.

We have two types of basic testing:

Unit testing is the process of creating code for automatically testing small, isolated pieces
of code from a TypeScript component. Unit tests do not use external resources, such as API
connection, network resources and databases; but mocked values and mocked services and
modules.

Integration testing is the process of creating code to test what’s going on between your
TypeScript component and your HTML template.

There are other kinds of automated tests, like performance testing, functional testing, end-
to-end testing (whole app, replicating user behavior) but today, we’ll focus only on unit tests.

Gotta catch’em all!


I developed a simple app with a search input, an autocomplete option list and a visual input
of the selected option. It’s a completely functional app, with modules and services
connecting to the API, interfaces to set variables types and store management; but just the
manual test will not assure it’s working properly and the repository now has a test coverage
metric to accept new pushes.

So, we start opening the terminal and running the CLI command:
ng test

The ng test command builds the application in watch mode (so every new component code
will be tested and every new test code will be counted, as soon as it detects the change) and
launches the Karma test runner - it’s native, as said before. The console output will show a
lot of errors but not because the app is crashing or there are syntax errors, it’s just because
there is written code but not built test codes.

Every time a new component, module or service is created via ng generate … or ng g …


command, the Angular CLI will automatically create the *.spec.ts files. These files contain
basic testing code but still not enough after importing services and other plugins to the
components. Karma will always search these files for running tests.
There are three main functions we use on Karma testing:

describe() is a group of related tests, all the functions cited below must be grouped
inside a describe function. Usually we use the component/service name here and
declare start variables with each component and module used here.

beforeEach() is a group of settings we must define before each it() instruction. So


every time a it() block of instructions is tested, the beforeEach() block will be called.

it() is a specific test, exactly the function or piece of code you are testing, what
should do and what should the test expect.

We also have the optional functions:

beforeAll() is a group of instructions to be executed, literally, before all it().

afterAll() is a group of instructions to be executed, literally, after all it().

afterEach() is a group of instruction to be executed after each test, cleaning


variables and instances.
Angular CLI will automatically import the component we are testing on the *.spec.ts file,
creating a component declaration (let component: …) and a fixture from this component (an
accessory to testing, able to detect changes, rendering, destroy, etc.) on the describe() top.

Next, it will automatically create a TestBed with the base component required to run the test
and set it to detect changes from the declarations. In the future, we’ll add components and
modules used in the code here as well.

And finally, it will includes a it() clause, always expecting to create the component properly.

This another command will show us the code coverage.

ng test —-code-coverage

It will create a new folder on the project, with a index.html to navigate in all objects coverage:
As below, the functionalities objects have almost no test coverage. Clicking the folder path
will show us the files and their coverage details.
How can we fix these error messages?
● ‘Object’ is not a known element

First, we need to import used modules into our TestBed. It works as a *.module.ts file,
declaring components used and modules to import.

Then, import CUSTOM_ELEMENTS_SCHEMA for children components.

● NullInjectorError: No provider!
The first instinct after reading messages like these is to import HttpClientModule on “imports”
array in TestBed.configureTestModule, but that’s not the case. HttpClientTestingModule is
the module used to test connection, but on the service itself, not on the component.

On Store error messages, we must import provideMockStore as a provider.

Some modules require their respective TestingModules (HttpClientTestingModule,


RouterTestingModule, BrowserTestingModule, etc), not the main module. Finally, after all
imports, Karma will no longer outputs errors:
But this is only for the “should create” tests work with Karma and Jasmine, native in Angular
CLI projects. In PatientNow projects we are using Jest, another framework solution who
operates above Karma to test. It allows a lot of resources; to spy on functions and objects,
creating a better user experience test line. So, after a installing Jest on Angular, their
@types and configurations for Jest, we are running it through new commands:

npm run test


npm run test:watch
npm run test:coverage

Using Karma and Jest are basically a JavaScript language code, it’s not an alien language
or rocket science. As we noticed in the code coverage html before, there are lines and
statements not covered in tests, so we must pass through these small pieces of code to get
the best quality tests possible.

Clean code programming and clean tests


The “clean code” premise brings a new vision to code readability and maintenance. Keep
things on simple functionalities, be clear about variables and functions naming, there are a
lot of points approached in many books and articles around the web. The main point to
create unit tests are

Instead of:

We must set the variable in a separated function, as we said before, to test the piece of
code. Isolating the functionalities is a way better to program and to run the tests:

This way, we can test with better controls.

How to test code


We need to identify our functionalities not covered by tests yet, so the coverage html will
indicate us where we must act. Let’s start with our simpler component, the ScreenContent,
who shows us the visual result after the search.

Let’s create a mocked result based on the API result, in a separate file (remember, clean
code!):
As we use a store management in this project, we must mock a Store provider with the
selector involved:
We can test our variable start value:

Our toggle function:

As it’s easy to read, we manually started the variable to indicate their previous state,
activated the function and ended up expecting a value. That’s the main syntax for every test
coding.
Here, we use the click on HTML element to test and use whenStable() to wait the change:

After these tests, we easily reached 100% coverage on this component:

Services are even easier to test, as we must import the HttpClientTestingModule and take
on the functions to GET/POST/UPDATE/etc.

Note, as we must create the mocked results for every function:

A few errors must shows up during “npm run test” command, like these. It’s because we
must assure in our code this variable must not be undefined.
Test first (TDD) or code first?
In my opinion, there are things we can import to test before or during a development.
Importing modules like HttpClientTestingModule, RouterTestingModule, Angular Material
modules are essential to include on test files at the same time as we import
HttpClientModule, RouterModule and Material modules to the module.

For other things, as a function test, it’s better to be tested after the functionality is done and
working.
Don’t be a Team Rocket member!
Don’t commit a crime in Angular testing!

● Don’t import a big module every test file.

It will take A LOT longer to test. Importing AppModule or others main modules (like
“BillingModule”, “SchedulerModule” etc) will bring a lot of code to test and even circular
dependencies. Take care even if it’s a SharedModule.

● Don’t import all children components!

Don’t import all children components and create stances and fixtures for it. It will eliminate
error messages but it will take longer to test, as the example before.
Instead, use CUSTOM_ELEMENT_SCHEMA, as explained in “How to fix..”.

You might also like