"Cucumberizing" Your Protractor and Karma Tests in AngularJS

Datetime:2016-08-23 02:51:08          Topic: AngularJS  Unit Testing           Share

This is a theoretical blog post on how to use Karma and Protractor in a BDD fashion.

I recently finished reading  BDD In Action by Johnathon Smart- a very awesome book on . In fact, it was this book was what really introduced me to BDD, gherkin, and step definitions. In the book he specifically talks about "switching over" your unit tests to acceptance tests whose low-level step definitions are implemented like unit tests. Indeed, on page 21 there is a section title that reads, "Don't Write Automated Tests, Write Executable Specifications" . This is deep.  Don't  write automated tests isn't that what we are doing here?? Well yes, but when practicing BDD you want to think about it a different way. Let your Gherkin lead into your step definitions which naturally become a place to put the equivalent of the code for the unit test you might write otherwise. 

It All Starts With The Gherkin

Using Gherkin is an incredibly powerful tool. It's english-like syntax makes it approachable and easily readable by anyone on the team, even non-technical members. The Given-When-Then style is basically a way of breaking up a unit test in three phases: setup, action, and assertion. This keeps your code modular, more maintainable, and in smaller chunks, but it also has the benefit of being more reusable as you can implement a  given step once and implement it in many scenarios. The Gherkin allows you to write examples that illustrate how the software is to be used which is exactly what you want when writing automated tests (and just developing software in general!). 

Enter CucumberJS

Cucumber.js is pretty much  the tool for running Gherkin scenarios and step definitions in JavaScript. Simply run `npm i cucumber --save-dev` and you're off! You can run the cucumber binary, it'll look for your feature files, and execute them. Great! But actually it's not so great. In AngularJS there's some setup that needs to happen behind the scenes in order 

"Cucumberizing" Your Tests

This is a term that I made up, and it basically refers to using the "cucumber version" of your web/ui tests or unit tests. In AngularJS, we have Protractor, an excellent JavaScript wrapper over Selenium WebDriver that lets you code fully automated ui/e2e tests. There also exists a Github project called protractor-cucumber-framework . This is an excellent framework that has been working well for me. To use this, all you have to do is change your protractor.conf.js file to use 'protractor-cucumber-framework'. Then in your step definitions you can call broser.get(..) and all the usual protractor commands will work. Similarly, you can "cucumberize" your unit tests by using a framework that combines karma and cucumberJS. This is important because in AngularJS you need the  window  available, and the Angular framework, injector, etc. must be set up in order to properly execute your tests for an AngularJS project. At the current time of this writing it's not as straightforward to find a great karma-cucumber library. There's "karma-cucumber" which says it's no longer maintained and redirects to "karma-cucumberjs" which also  seems to be no longer maintained. The one I recommend now is karma-cucumber-js, a lower-starred project on Github, but it's active. Also, the core contributor  eugene-sea   assured me that he would maintain it and answer issues that I open. hehe.

BDD Without "Cucumberizing"

Towards the end of John Smart's  BDD in Action,  there is a section titled, "Practicing BDD with traditional unit-testing tools" (page 285). He recognizes that some teams may be unable or unwilling to cucumberize their tests. However, he gives some great tips for keeping a, "BDD state of mind" while using non-cucumberized Karma or Protractor. 

- Write test method names that describe behavior

- Use test class names that provide context: a useful trick is to prefix it with "when". Here's a Java example that might illustrate this a bit better:

public class WhenUpdatingMyBirthDate {

  @Test
  public void should_be_able_to_edit_birth_date_on_profile_page

  ...
}

- Use fluent assertions. This is basically the BDD "expect" syntax for assertions, like this chai assertion for example:

expect(obtainableStatuses).to.have.length(3).and.to.incluge('Gold');

Without Cucumber, the answer to, "How do I do automated testing in AngularJS?"  is pretty straightforward. Google has built two amazing good tools Karma and Protractor which are test runners that execute unit tests and ui/e2e tests, respectively.

Web / e2e Tests     |       Unit Tests

With Cucumber

Feature

Scenario

|

Web / e2e

Step Definitions

Feature

Scenario

|

Unit Test

Step Definitions

How do I actually do this?

Start with this:

Then change it to this:





About List