Since Angular’s official release in September 2016, a lot of ink has been spilled over the ground-up rewrite of AngularJS. While the quantity of informations is huge, it seldom addresses tips on how to solve specific problems. This has led me to write this serie of posts about my journey with Angular. In this post, I will focus on testing tips. If you are unfamiliar with Angular testing, you can check out this very good tutorial from codecraft.
Destimator
First, I created an application called Destimator which estimates your death risk. Pretty crazy right ! Well it was hard to find an original idea with all those demo apps in the wild but no worries, nothing is scary, after all we are here to talk Angular ;) It is splitted into two parts:
estimation-form: Responsible for rendering the form and display the result.
estimation-logic: Business logic for calculating death risk.
estimation-logic.service.ts: service to calculate then estimate death risk
score-range.service.ts: service to retrive data from api
score-range.model.ts: model for communicating with api
Destimator’s repo is publicly available on my github here. If you dare to try it Now, that we have a basic understanding of the roles, we can move to the testing part.
Testing
Frameworks tip
The project was generated using Angular-CLI. The testing uses the very popular Jasmine framework for testing, asserting and even mocking. I prefer to let Jasmine take care of the testing part only while Chai handle the assertion part and Sinon the mocking part. It’s a choice driven by Separation of Concerns (one thing should do one thing only and do it well) although some might argue that this is JavaScript fatigue all over again.
Bare with me for the time being, I hope to convince you by this post’s end.
1
npm install -D chai sinon
First test technique
Testing an angular component consists on preparing a standalone module that will contain every dependency your component and its template require to run. While most people will copy paste or generate a testing file, I prefer to start with an empty module. Why ? Because understanding dependencies helps me while debugging and tuning my application. In this example, I want to test my estimation-form.component, so my approach is:
As you can see, my test is simply checking if I have set the right keys in my reactive form group. Although the test will very likely pass (unless I made a typo somewhere), it won’t run because my testing module doesn’t contain my component’s dependencies. Let’s try to run it and see the error:
1
npm test
The output is:
1
2
Error: Template parse errors:
Can't bind to 'formGroup' since it isn't a known property of 'div'. ("<div class="row" [ERROR ->][formGroup]="estimationForm">
Well, this means that our component is dependent on the ReactiveFormsModule which contains the formGroup directive. With some little magic:
let fixture: ComponentFixture<EstimationFormComponent>;
let comp: EstimationFormComponent;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
// Adding the required module
ReactiveFormsModule
],
declarations: [
EstimationFormComponent
],
providers: []
});
...
If we run it again, a new error appears:
1
2
3
Error: Template parse errors:
'md-icon' is not a known element:
If'md-icon' is an Angular component, then verify that it is part of this module.
Again, our component’s template is using Angular Material components without importing the MaterialModule in our testing module. Fix it by importing that module. I won’t go through all error messages because it’s not my point. What I wanted to explain by the simple test approach is that you probably need to spend some time understanding what your component requires to run before starting to test it. This might seems time consuming but if one single test can help remove duplicated dependencies, optimize my code and discover more about Angular modules, it might be a good time investment.
Isolation technique
Let’s fast forward to where we finish setting up all dependencies, our file should look like this:
The test passes successfully but did you notice something weird about our dependencies ? We are importing the HttpModule. How is this possible?! Tests are supposed to be isolated. Well, if we take a look at the ScoreRangeService:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Injectable()
exportclassScoreRangeService{
// Http dependency
constructor(private http: Http) { }
getRange(score: number): Observable<ScoreRange> {
returnthis.getRanges()
.map(res => res.filter(r => score >= r.maxScore))
.map(res => res[res.length - 1]);
}
private getRanges(): Observable<ScoreRange[]> {
returnthis.http.get('../../api/score.range.json')
.map(res => res.json().ranges as ScoreRange[]);
}
}
We will notice the dependency on the http service in the constructor, so how can we eliminate that. Certainly, we won’t change our service’s implementation but rather modify how our testing module is providing it by using a fake implementation. How can we create a fake implementation ? This is where Sinon shines ! Told you we will get back to this ;) By using the createStubInstance method of Sinon with no effort. The mock consists of an object with the same keys and signatures as the original implementation so no Angular nor typescript will detect the difference.
Technically, this would work but in practice you will encounter this error:
1
2
TypeError: Attempted to wrap undefined property estimate as function
at wrapMethod (http://localhost:9876/base/src/test.ts?ae8b7e95826ca6c1ffc4a2d5aadc1d417ff137d0:27854:21)
The message explain that we can’t wrap an already wrapped function. Remember we created a stub using createStubInstance then we used a spy which in turn will attempt to create a stub from a stub. Unfortunately, Sinon doesn’t support chaining stubs so what is the solution ? Javascript magic ! This might sound stupid but actually it works fine and it’s also very useful. My advice in such situation is to create fake shell classes, same method signatures but without a body, just like an empty shell. Check out the implementation for FakeEstimationLogicService:
My last tip is about async tests. It’s a special kind of tests designed for asynchrounous code. What’s special about asynchrounous code? We don’t know exactly when the result will be avaiblable. It’s just a promise that we should examine at the right time otherwise our assertion won’t make any sense. Let’s take the example of our email input. Instead of immediatly checking the input when the user starts typing, we want to give him/her some time to finish up. That should provide a better user experience.
In this case, we will defer checking format by 500 ms using debouceTime operator like the code below:
.nativeElement.innerText).to.be.eql('Please enter a valid email address');
});
When this test executes, our expect assertion will simply happen before debounceTime has finished so it will fail. How can we fix it ? Well, some special tools are required.
fakeAsync and tick
fakeAsync and tick are provided by @angular/core/testing. The fakeAsync executes our test in a fake async zone while tick blocks execution and simulates time passage. Let’s see how our test will look like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
it('should display error message when email is not valid', fakeAsync(() => {
.nativeElement.innerText).to.be.eql('Please enter a valid email address');
}));
async and whenStable
Although the syntax is a little different but the purpose stays he same. The async wraps the code in an async zone while whenStable will only execute when all pending promises are resolved. This is a rewrite of the previous test using async and whenStable:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
it('should display error message when email is not valid using async', async(() => {
.nativeElement.innerText).to.be.eql('Please enter a valid email address');
});
comp.ngOnInit();
comp.estimationForm.setValue({
cheatingOnPartnerLvl: 2,
adrenalineDose: 29,
hasSuperHeroFriend: false,
email: 'bad_email_format'
});
}));
jasmine done
While the previous tools were provided by Angular, Jasmine also provides its own mecanism to test asynchronous code. It’s based on a function usually called done and passed into the parameters of the test. This function should be called when all async processing is complete like the following example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
it('should display error message when email is not valid using done', (done) => {
.nativeElement.innerText).to.be.eql('Please enter a valid email address');
});
done();
});
Like demonstrated above, there are 3 different approaches to test async code, it’s up to the developer to choose. Personally, my favorite is the first one with fakeAsync and tick because it make my code look synchronous therefore easier to understand and debug.
This is the end of this first post on Angular journey, stay tuned for what’s next !
Estimation is a very important part of scrum. It allows the team to evaluate how much work is needed to finish an item and therefore conclude what can be delivered next sprint. It also helps product owners prioritize their items by taking into consideration the required amount of work. An item that takes too much time to be done usually has a lesser priority than another that can be finished quickly. Estimating the right way is essential in scrum to get the best possible results.
Yeah, i know … The first question that pops into your minds is: Doesn’t people get tired of writing this bla bla over and over again ?!! My Code is perfect and I don’t need no steps to tell me what to do and what not to do … Well , I believe that if our codes where so perfect we wouldn’t spend debugging it , creating break points and buying new keyboards !! Come on, it won’t take you over 10 minutes to read and perhaps avoid looking like this.
It all started with this article posted by a good friend of mine about his way of implementing the factory pattern.
Although there is nothing to approach about his way, something kept itching me to write a second article about another design pattern that might fit in this situation as well.
This guide is destined to help people visit the eastern coasts of Canada and United States. It will cover the following Cities: Montreal - Ottawa - Toronto – Niagara Falls (Canadian & US Sides) - Chicago - Miami - Washington DC - New York. I will focus more on what you need to bring and how to travel from one place to another. I will only be suggesting how much time to spend in every town but it’s really up to you to choose what to see and do in every town. Finally, this guide is based on my personal experience and I’ll be happy to answer any questions you might have. If you like it, share it!
In scrum, only three roles exist: Product owner, Dev team and the scrum master. While the product owner is responsible for driving the project and the dev team is in charge of realizing it, no one really knows exactly what the scrum master’s role is. Is he the one who animates the daily meetings, the poker plannings and retrospectives ? Or may be he is manager of the dev team?
IT projects have some similarities with industrial ones like budgets, deadlines but also have its differences like its flowness and unpredictable complexity. Many ways exist today to drive this kind of projects, perhaps the most used one is Waterfall methodology. It has been the standard for managing software development projects since it’s creation in the mid 20th century. However, the outcome was very disappointing.
Cleaning up old files is an incredebly annoying operation. It’s time consuming and might result into errors due to repeating the same actions all the time. However, it’s necessary to remove old files in order to keep your folder clear and gain free space on your hard disk.
Since the beginning of time, hierarchy existed almost everywhere from small families to large companies and even in criminal organizations. Wherever you go, there is someone in charge of taking decisions while others simply execute them. It seems like a proper way to instaure order and move forward. However, i think we haven’t taken a moment to ask ourselves if this is the best way to do so?
Since Angular’s official release in September 2016, a lot of ink has been spilled over the ground-up rewrite of AngularJS. While the quantity of informations is huge, it seldom addresses tips on how to solve specific problems. This has led me to write this serie of posts about my journey with Angular.
Welcome to another post about my Angular Trip, this time i’ll be covering SEO optimization with Angular apps. If you didn’t read my previous post about testing, you can find it here.