Let me briefly talk to you about angular testing.
How do you design your angular applications to be testable?
How do you design the tests for your angular application?
How do you execute the tests and make sure that
your angular application is satisfying all the tests that you've
written even as you're developing your angular application?
Now this is where I would also briefly talk about
test driven development of angular applications.
Interestingly, angular itself has been built from ground-up to enable testing,
to be part of your angular application development.
The main force behind angular Misko Hevery was himself a Google test engineer and hence,
his influence on designing angular to be testable from
ground-up can easily be seen all over the framework.
So, angular itself as you have understood from the previous lectures and exercises,
is modular in nature.
So the modules of angular together with the components and
their templates and then the services and the pipes and the directives,
mean that angular lends itself easily for being tested.
Now, because the angular application itself is composed of these various parts,
you can test each of those parts in isolation first
even before they become part of the entire angular application.
The second aspect is the dependency injection mechanism that angular leverages
for supporting the combination of the various parts of
your angular application itself means that you can easily substitute mocks
for those dependencies within
your various parts of the angular application and carry out tests.
I have used the word mock in,
in the previous sentence will come to understand
that in a bit more detail and more that, later slides.
This is where we need to be aware of
an approach for doing application development called test-driven development.
In test-driven development, as you can understand by the name itself,
means that you first write automated tests for
all the functionality that you desire to implement within your application.
So first comes the test,
thereafter you write your application code in order to pass the test.
So the test itself specifies what functionality you want to implement.
Thereafter you write the code to implement that functionality.
Since you already have the test in place,
you can test to see whether the implementation that you do satisfies the test or not.
Now, of course, once your realization of your functionality satisfies the test,
you can always refactor the code to comply with their software engineering standards.
But even after that,
you can retest the code to make sure that it still satisfies
those requirements specified within
that specific test that you use within your test-driven development.
So indeed, test-driven development is
a very viable approach for designing
good application from the ground-up to be fully tested.
Now when we talk about testing,
you can approach testing from several different aspects.
The first and foremost is that if your application
itself is implemented as various pieces,
like components, like services, like directives,
like the pipes that you are implementing within your application.
That means that you can easily test each of these individual units in isolation.
So that is where unit tests come to the fore.
Unit test means that you're testing the individual units of code,
making sure that that particular individual unit
satisfies the functionality that it is supposed to support,
and that functionality and the logic within that piece of code is implemented correctly.
Now isolating the unit and testing it is very,
very useful to figure out most of the initial problems within your,
within your code and then fix them even before you integrate that patch into the code.
Now once you start integrating these parts into the whole,
it becomes even more cumbersome to be able to carry out detailed tests of your code.
So, hence, isolated unit tests form the first line
of defense against bugs when you are developing your application,
specifically your angular application.
Now as we see with an angular,
we have a clear separation between the angular components and the DOM itself.
So within a component, for example, there,
the logic of your component is implemented completely in
the typescript code that you implemented within a component that typescript files.
And then the DOM itself is controlled through
the template that you have designed for your angular component.
So Beta itself, you see the clear separation between the two.
So you could simply test just the logic of
your component code itself without writing a vertical template.
But then you could also consider the two together and then evaluate those aspects.
As we will see in the exercise that follows this lecture,
we will actually do both of these approaches.
Not only that, the fact that angular uses
dependency injection means that you can inject mock dependencies within your application.
When I say mock, I mean, for example,
if your component does dependent on a particular service you can always implement
a mock service that mimics the behavior of the service
and then substitute into place while you're testing the component so that you can keep
your component independent of how the service is actually implemented.
As long as the interface between your component and the service is properly designed
you can substitute a mock service in place and still test your component.
There, from the mock,
you can easily control what is supplied to the component from the service.
So this approach enables you to do unit testing
in great detail within your angular application.
This is where the availability of testing frameworks like "Jasmine".
So what Jasmine provides is
a behavior driven testing framework that is completely designed in JavaScript.
Now, this Jasmine framework is a general framework that
is available for testing any JavaScript applications.
Angular adopts Jasmine as the approach for specifying our tests for other angular parts,
their components, the services and various aspects of our angular application.
Now, within Jasmine, Jasmine uses two things that comes to your aid.
One is the use of a "describe" function.
The "describe" function enables you to group a set of tests and then
execute these tests together as a single group of tests.
When we write the code in the exercise you will see me
enclosing a set of tests inside a describe function.
Then we write our code for our,
the Jasmine code, for our angular tests.
Now within these "describe" functions you'll also use what is called as "it" functions.
The "it" functions enable you to specify
individual tests that you want to carry out on your angular application.
So that is where you will see me specifying "it" and then specify that
the nature of the particular test and then
design the code for that particular test with an in "it" function.
So as we design the code in the exercise look out for the "describe" and
the "it" within your angular test applications.
Once you've designed the test with the Jasmine framework,
Karma is a JavaScript based command line tool
that enables you to carry out these tests automatically.
Now, Karma together with Jasmine,
enables you to carry out tests for your angular application.
Now with Karma, what Karma supports,
is that it enables you to spawn
a web server within which you load your application source code and
then Karma then uses a browser to carry out the actual tests of your various units.
So this is where when you run your tests using Karma,
you will see Karma stacking up a browser,
whether it is a browser window of an existing browser or
whether you would use something called PhantomJS which starts
a phantom browser behind the scenes to carry out the test.
It doesn't matter, but Karma uses
the browser in one moment to carry out the test for your angular application.
As you will see in the exercise that follows,
this is where if one of your colleagues keeps insisting that his or her implementation of
a particular piece of your angular application is
correct and keeps emphasizing the point,
you can always design a few tests using Jasmine and
Karma and then carry out the tests and should the tests fail,
you can always disprove their argument.
So that is when you can turn,
turn around to your colleague and say,
my Karma ran over your dogma.
Now, of course, your angular applications are not completely devoid
of the involvement of the angular framework itself.
Your component cannot be designed by yourself without
using many of the library functionality that angular provides for you,
although some of the basic logic can be tested independent of angular.
What we call as isolated tests.
But, more and more,
you will find that unless you in,
want the angular frame support itself you
will not be able to carry out much of the test of
your angular parts whether it is components or services or pipes or directives.
So this is where the angular testing utilities provide
a test environment that enables you to carry
out the unit tests within your angular application.
So the angular testing utilities as you will see me using in the exercises,
in the very next exercise,
will provide us with certain implementations of angular functionality that you use
within your tests in order to set up the environment where you can carry out their tests.
So, this is where the interaction with the angular environment,
instead of using the real angular implementations,
you will use this test utilities that will provide
sufficient functionality to enable you to carry out the tests.
And this is where the TestBed that we will
use within our angular application is very, very useful.
The TestBed essentially creates an angular testing modular.
As you realize, your components don't exist by themselves.
Your components have to be included inside an NG module.
Now you can't simply use a standard NG module for carrying out your testing.
So that is where the TestBed,
that is supported by angular test utility,
provides you with an NG module environment that enables you to test their components.
So, within the TestBed,
you will use something called TestBed Create Component to create
an individual component and an instance of the component to carry out the tests on that.
And when you do that
the TestBed gives you access to something called the ComponentFixture,
the ComponentFixture is something that provides you a handle that enables you to surround
your component with enough functionality such that the component can be tested by itself.
The fixture provides access to the component itself and
then also through that we will use something called the DebugElement.
You will see me using that in the exercise that follows.
The DebugElement gives you access to the DOM,
that is the the template that is supported as part of your component.
So thereby, you can do manipulations on the DOM like clicking of elements in the DOM,
getting access to a DOM element and then reading out what is enclosed
inside those Dom elements and so on which will enable you to carry out the tests.
Now, before we go on to the exercise,
I want you to be aware of some of these things so that when we encounter them in
the exercise itself you will see why I am making use of each of these different pieces.