This site uses cookies for analytics, personalized content and ads. By continuing to browse this site, you agree to this use. Learn more
Microsoft Logo
Gray Pipe
  • Developer Network
    • Downloads
      • Visual Studio
      • SDKs
      • Trial software
    • Programs
      • Subscriptions
      • Students
      • ISV
      • Startups
      • Events
    • Community
      • Magazine
      • Forums
      • Blogs
      • Channel 9
    • Documentation
      • APIs and reference
      • Dev centers
      • Samples
      • Retirelanding
Developer Network Developer
MSDN subscriptions
Get tools
magazine
  • Issues and downloads
    • All issues
    • 2019
      • February 2019
      • January 2019
    • 2018
      • Connect(); 2018
      • December 2018
      • November 2018
      • October 2018
      • September 2018
      • August 2018
      • July 2018
      • June 2018
      • May 2018
      • April 2018
      • March 2018
      • February 2018
      • January 2018
    • 2017
      • Connect(); 2017
      • December 2017
      • November 2017
      • October 2017
      • September 2017
      • August 2017
      • July 2017
      • June 2017
      • May 2017
      • April 2017
      • March 2017
      • February 2017
      • January 2017
    • 2016
      • December 2016
      • Connect(); 2016
      • November 2016
      • October 2016
      • September 2016
      • August 2016
      • July 2016
      • June 2016
      • May 2016
      • April 2016
      • March 2016
      • February 2016
      • January 2016
    • 2015
      • December 2015
      • November 2015
      • Windows 10 issue
      • October 2015
      • September 2015
      • August 2015
      • July 2015
      • June 2015
      • May 2015
      • April 2015
      • March 2015
      • February 2015
      • January 2015
    • 2014
      • Special 2014
      • December 2014
      • November 2014
      • October 2014
      • September 2014
      • August 2014
      • July 2014
      • June 2014
      • May 2014
      • April 2014
      • March 2014
      • February 2014
      • January 2014
    • 2013
      • Government 2013
      • December 2013
      • November 2013
      • October 2013
      • September 2013
      • August 2013
      • July 2013
      • June 2013
      • May 2013
      • April 2013
      • March 2013
      • February 2013
      • January 2013
    • 2012
      • December 2012
      • November 2012
      • Windows 8
      • October 2012
      • September 2012
      • August 2012
      • July 2012
      • June 2012
      • May 2012
      • April 2012
      • March 2012
      • February 2012
      • January 2012
    • 2011
      • December 2011
      • November 2011
      • October 2011
      • September 2011
      • August 2011
      • July 2011
      • June 2011
      • May 2011
      • April 2011
      • March 2011
      • February 2011
      • January 2011
    • 2010
      • December 2010
      • November 2010
      • October 2010
      • September 2010
      • August 2010
      • July 2010
      • June 2010
      • May 2010
      • April 2010
      • March 2010
      • February 2010
      • January 2010
    • 2009
      • December 2009
      • November 2009
      • October 2009
      • September 2009
      • August 2009
      • July 2009
      • June 2009
      • May 2009
      • April 2009
      • March 2009
      • February 2009
      • January 2009
  • Subscribe
  • Submit article
search clear
We’re sorry. The content you requested has been removed. You’ll be auto redirected in 1 second.
Issues and downloads 2018 December 2018 The Working Programmer - How To Be MEAN: End to End

December 2018
Volume 33 Number 12

[The Working Programmer]

How To Be MEAN: End to End

By Ted Neward | December 2018

Ted NewardWelcome back again, MEANers.

In the last piece, I talked about unit testing, which verifies that the code on the client is working correctly. However, most of the time unit tests look to mock out the back-end interaction, in favor of creating a more deterministic set of test results; that’s useful, but not sufficient, much of the time. Sometimes, you really need to make sure the front end is communicating effectively with the back end, particularly when both are in flux—changes to the JSON exchanged between the two, for example, can each be unit-tested as correct within themselves, but once you start actually passing data across the wire, they can disagree, and break. Nobody wants that, particularly since (as every developer with more than three years’ experience can tell you) it will only happen when you’re doing a demo in front of somebody much higher in the org chart than you.

This is the province of Angular’s end-to-end (e2e) testing, and where unit testing looks to test each component individually and, isolated away from the rest of the system, e2e testing looks to test the system as a whole. This makes e2e testing more brittle, since it depends on a lot more factors, but it’s also just as important as unit testing in the long run.

Back to the Beginnings

As with the unit-testing discussion, Angular tries to make sure that testing is available from the beginning of your greenfield application by building some basic scaffolding in place when the application is first generated (assuming you use the Angular command-line interface [CLI] tool). The e2e directory, off the root of the project, contains the necessary code to run an end-to-end test, so I’m going to give it a spin before doing anything else: “npm run e2e” launches the end-to-end testing, and unlike the unit-testing tooling, e2e runs through a test pass, then halts. The intent here is that the unit-testing tooling should be running near-constantly during development to verify that things are working “in the small,” and the end-to-end tests should be run only when it’s time to verify that no regressions popped up.

The default test is just to verify the scaffolded app’s “Welcome to app!” message, so one easy first change is to modify the App­Component’s title property (remember, from way back when we first started, that property is in app.component.ts) to “SpeakerApp” and check to see that it shows up. (Don’t forget to change the unit test in app.component.spec.ts, too, by the way.) Make that change, make sure the unit tests pass, then run “npm run e2e” again and note the failure. Well, try to note the failure—the browser closes down but the console window in which you ran “npm” will highlight (in red) the test failure.

So, the next step, then, is to modify the end-to-end tests to reflect the change you’ve made to the code.

Of Pages and Objects

End-to-end testing uses the ProtractorJS framework (at protractortest.org) to run the browser in an “automated” mode, and the code to drive Protractor lives in the app.po.ts file. The “ts” suffix should be pretty familiar by now, but the “po” stands for page object, which is a common idiom in the Web end-to-end testing world. A page object is, literally, an object that represents all the actions possible on a given Web page, so the app.po.ts page would represent the application’s home page, according to the naming convention. Sure enough, if you have a look at it in the editor, you see:

JavaScript
Copy
import { browser, by, element } from 'protractor';
export class AppPage {
  navigateTo() {
    return browser.get('/');
  }
  getParagraphText() {
    return element(by.css('app-root h1')).getText();
  }
}

Note that the code here isn’t doing any testing—this is literally a bundle of code that serves a utility role for the end-to-end tests, and nothing more. The navigateTo method simplifies bringing this page up in the browser, and the getParagraphText method simply extracts the text for the title by using a CSS selector to find the H1 element out of the DOM that corresponds to the app-root component. As a matter of fact, that’s probably a misnamed method—it really should be called getTitleText, so let’s make that change and do the corresponding change in the actual test code. (Note that if you monkey around with the browser’s title, via the <title> HTML tag, you might want to rethink the method name again, but because this isn’t a production app, I’m not going to stress over it.)

Now open the other file in the e2e directory, app.e2e-spec.ts:

JavaScript
Copy
import { AppPage } from './app.po';
describe('full-app App', () => {
  let page: AppPage;
  beforeEach(() => {
    page = new AppPage();
  });
  it('should display welcome message', () => {
    page.navigateTo();
    expect(page.getParagrahText()).toEqual('Welcome to app!');
  });
});

Here you can see the usual Jasmine test format, with the describe method and it functions, and notice how the test fires up an AppPage instance, navigates to it, then tests to see if the paragraph text matches the expectation. I know there are two changes I need to make—one to use the renamed getTitleText method, and the other to change the text to “Welcome to SpeakerApp,” in order to reflect the change in the title. Once those changes are made and “npm run e2e” is invoked, everything’s green again.

Protractor 101

The Protractor Web site has the complete documentation set, but fortunately most of the Protractor API is pretty self-documenting, at least from a high-level perspective. The Protractor home page has an example of a relatively simple end-to-end test that exercises a “to-do” list application, demonstrating how to find elements on the page by using either CSS selectors (element(by.css(…))), model object (element(by.model(…))), or even grabbing a collection of elements via an Angular repeater (element.all(by.repeater(…))), which can then be counted and individually examined, as desired. The Protractor tutorial also mentions that elements can be obtained by HTML identifier (by.id(…)) and by binding, meaning the element is bound to a given variable (by.binding(…)); these are all collectively known as ElementFinders in the Protractor documentation, in case more details are needed.

Once the e2e tests are set up and running, however (and the default Angular CLI scaffolding gives a strong leg up on that, given that it provides a starting point), really, writing e2e tests is about the same as writing any other tests: arrange, act, assert. Given that this is a Javascript-based world, of course you can change the testing framework you use if you so choose, but assuming you work with the same tools out of the box that the CLI establishes, you’re already on your way towards writing a comprehensive set of e2e tests.

One thing that bears mentioning: whether or not you use page objects is entirely your personal choice, but, frankly, given that e2e tests tend to be more “macro” tests (meaning, you typically don’t test just one page or component, but a whole series of steps) and/or user-acceptance-style tests, it’s generally helpful to have page objects in place to make the tests easier to read and—particularly—maintain. Remember, UI tends to be one of those things that shifts often during user demos, and the page object approach can help minimize the “churn” that can happen to e2e tests because of user changes.

Incorporating Server Bits

Given that I suggested that running the end-to-end tests means using the server, and that running the e2e tests should be a pretty common thing, it’s probably a good idea to make sure that running the e2e tests also fires up the server. Otherwise, humans have to remember to run something before running the e2e tests, and that’s usually a recipe for frustration in the long term. One way to do this, of course, is to write a batch file or PowerShell script to run both; another approach is to simply edit the package.json that Angular generated to have the “e2e” part of the file issue the right shell commands to launch a local version of the API server. (It’s not a flawless approach, but it serves for now.) That way, you remain consistent with the Angular CLI conventions.

Assuming that the server parts are in a subdirectory called “server” (and that you’re using the LoopbackJS-based server I wrote back in October, 2017 (msdn.com/magazine/mt826349), then all you need to do is get “npm run” to issue a “node server” command, which will drop into the server directory and issue a “node .,” which is enough to launch the Loopback bits:

JavaScript
Copy
{
  "name": "full-app",
  // ...
  "scripts": {
    "ng": "ng",
    "start": "ng server",
    "build": "ng build --prod",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "start node server & ng e2e"
  },
  // ...
}

The “start” in front of the “node server” is to tell the shell to spin off node server into a separate command window; this will have the unfortunate side effect of leaving the server window running after the e2e tests finish, but it suffices for now. (If this really creates heartache, replace the two commands with a batch file or PowerShell script, and then you’re in best-of-both-worlds territory.) Now, the server is up and running, and the client can start making calls to it.

Arguably, for this to be a true end-to-end test, the e2e tests should be operating against a shared server, but then you’re back to the problem of non-determinism in the tests. Others may disagree, but I prefer a local server over a remote/shared one for this sort of testing.

Wrapping Up

By the way, although it realistically shouldn’t be a concern by this point, as of this writing, the Angular team just released Angular 7. This means this column has seen at least six significant releases of Angular since its start, and given that none have created any major rewrites on our part, that should give us a certain comfort level in adopting Angular for any long-lived application and, hopefully, addresses a few of the concerns toward adopting Angular in your company or team.

On a logistical note, this column marks the 30th article written on the MEAN stack, and while there’s clearly more I could delve into, the name of the column is “Working Programmer,” not “MEAN Programmer,” and it’s time to move on. Angular’s cool and all, but this could go on ad infinitum, and there are lots of other interesting things out there to explore: new C# features, new F# features, and maybe I’ll even take a dive into the inner workings of the CLR, or a JavaScript engine (either V8, the one that ships with NodeJS, or Chakra, Microsoft’s version of V8), for a bit. Before ending, though, let’s be gracious consumers, and say, thanks, Angular, for all the good memories over the last few years, and we’ll be seeing you around. Keep up the good work, and we’ll drink a toast to you when you hit Angular 10 and 15 and 20 and so on. For now, though, fare well and smooth sailing.

As always, happy coding!


Ted Neward is a Seattle-based polytechnology consultant, speaker, and mentor, currently working as a director of Engineering and the director of Developer Relations at Smartsheet.com. He’s written a ton of articles, authored and co-authored a dozen books, and speaks all over the world. Reach him at ted@tedneward.com or read his blog at blogs.tedneward.com.

Thanks to the following technical expert for reviewing this article: Garvice Eakins (Smartsheet.com)


Discuss this article in the MSDN Magazine forum

The Working Programmer - How To Be MEAN: End to End

In his 30th—and last—column on the MEAN stack, Ted Neward covers end-to-end testing in Angular, which looks to test the system as a whole and tries to ensure that the front end is communicating effectively with the back end. Read this article in the ...

Dec 3, 2018

MSDN Magazine Blog

 

More MSDN Magazine Blog entries >


Current Issue


February 2019

Browse All MSDN Magazines


Subscribe to MSDN Flash newsletter


Receive the MSDN Flash e-mail newsletter every other week, with news and information personalized to your interests and areas of focus.

Follow us
  • https://www.facebook.com/microsoftdeveloper
  • https://twitter.com/msdev
  • https://plus.google.com/111221966647232053570/
Sign up for the MSDN Newsletter
Is this page helpful?
Your feedback about this content is important.
Let us know what you think.
Additional feedback?
1500 characters remaining
Thank you!
We appreciate your feedback.

Dev centers

  • Windows
  • Office
  • Visual Studio
  • Microsoft Azure
  • More...

Learning resources

  • Microsoft Virtual Academy
  • Channel 9
  • MSDN Magazine

Community

  • Forums
  • Blogs
  • Codeplex

Support

  • Self support

Programs

  • BizSpark (for startups)
  • Microsoft Imagine (for students)
India (English)
  • Newsletter
  • Privacy & cookies
  • Terms of use
  • Trademarks
logo © 2019 Microsoft