left-icon

Angular Testing Succinctly®
by Joseph D. Booth

Previous
Chapter

of
A
A
A

CHAPTER 4

Test-Driven Development

Test-Driven Development


Test-driven development is a software development technique in which the requirements are written as test cases, and the software is written/refactored to pass the various test cases.

ATM testing

An automated teller machine (ATM) is being created, and we are designing the software for it. We plan on a method called ShouldCashBeDisbursed() and expect a Boolean value to be returned. Code Listing 6 shows our initial code.

Code Listing 6: ShouldCashBeDisbursed function

public ShouldCashBeDisbursed(balancenumber , withdrawalnumber ) {

    let ans = null;

    return ans;

  }

At this point, our code does nothing except return a NULL. If you had created an interface, this code might be the default implementation for one of the definitions.

We start by writing our test cases, which we’d expect to all fail. Listing 7 shows our test cases.

Code Listing 7: Test cases

it('should dispense $200 when balance = $1000', () => 

{

  let ans = component.ShouldCashBeDisbursed(1000,200);

  expect(ans).toEqual(true);

});

it('should not dispense $200 when balance = $150', () => 

{

  let ans = component.ShouldCashBeDisbursed(150,200);

  expect(ans).toEqual(false);

});

We now write the code necessary to pass these tests. However, as you write the tests, you will likely think of additional tests you might want to add. What happens if the requested withdrawal amount is 0? Or a negative number? Thinking through your test steps can help you write a more robust method.

Once you’ve written your tests, you can go ahead and code the method. In addition to helping you think of your design, you’ve also built a regression test plan to ensure future changes to the method do not break previous features. Code Listing 8 shows our final test steps.

Code Listing 8: Withdrawal test cases

it('should dispense $200 when balance = $1000', () => 

{

  let ans = component.ShouldCashBeDisbursed(1000,200);

  expect(ans).toEqual(true);

});

it('should not dispense $200 when balance = $150', () => 

{

  let ans = component.ShouldCashBeDisbursed(150,200);

  expect(ans).toEqual(false);

});

it('should not dispense when withdrawal is negative', () => 

{

  let ans = component.ShouldCashBeDisbursed(1000,-200);

  expect(ans).toEqual(false);

});

it('should not dispense when withdrawal is 0', () => 

{

  let ans = component.ShouldCashBeDisbursed(150,0);

  expect(ans).toEqual(false);

});

Code Listing 9 shows our method.

Code Listing 9: AllowWithdrawal method

public ShouldCashBeDisbursed(balancenumber , withdrawalnumber ) {

    const shouldAllow =

    (balance - withdrawal > 0&& (withdrawal>0

    if (shouldAllow) {

      balance = balance - withdrawal;

    }

    return (shouldAllow);

  }

When we run this in the test runner (described in later chapters), the result is our expected passed tests. Figure 7 shows the test runner results.


Test results

Figure 7: Test results

Behavior-driven development

While test-driven development works, it is generally focused at the method level. This is fine for developers, but not necessarily for business analysts. They are more concerned with the behavior of the system, not the details of the methods. This is the focus of behavior-driven development (BDD). The business analysts write the expected behavior, which acts as a specification and a test plan for the development team.

Let’s look at how business analysts might expect the ATM withdrawal function to work. The business analyst will think in terms of the user and create user stories. The user story for the ATM might look like:

  • As a: customer using the ATM
  • I want: to be able to withdraw cash from my account
  • So that: I can take my spouse to dinner.

Using the Gherkin language, the business analyst will then write examples of how they expect the system to behave. For example,

  • Given I am using the ATM machine
  • When I withdraw $200 with a balance of $1000
  • Then I expect to be dispensed $200

And:

  • Given I am using the ATM machine
  • When I withdraw $200 with a balance of $150
  • Then I expect to be shown an “insufficient funds” message

So far, this is good, but now they add a couple more scenarios:

  • Given I am using the ATM machine
  • When I withdraw $0
  • Then I expect to be shown a “Please enter a valid amount” message

And:

  • Given I am using the ATM machine
  • When I withdraw more than the $300 daily limit
  • Then I expect to be shown a “Cannot withdraw more than $300” message

Now that the business analysts have written their expected behavior out, the developer realizes that a Boolean return value won’t work. The method needs to return a status code, since the error message needs to be different. Also notice that the business analyst never considered the negative amount case, since most ATM machines don’t have + or – buttons.

Summary

When the tests are written first, it forces more thinking and designing, instead of jumping in and coding right away. Whether the tests are written by developers or business analysts, the design work of writing the test plan first has several benefits:

  • Encourages thinking before coding!
  • Gives you a regression test base, ensuring nothing breaks after code changes.
  • Forms a contract between the specifications and the code.

There are many available tools for and variations of test-driven development. In the next few chapters, we will explore the Angular environment for working with this approach.


Scroll To Top
Disclaimer
DISCLAIMER: Web reader is currently in beta. Please report any issues through our support system. PDF and Kindle format files are also available for download.

Previous

Next



You are one step away from downloading ebooks from the Succinctly® series premier collection!
A confirmation has been sent to your email address. Please check and confirm your email subscription to complete the download.