Do Followers Matter?

So after posting for today on my publication, You Have Only 15 Minutes the webpage refreshed and I had my profile show only 26 followers. I thought it was a glitch and I refreshed again. It still…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




A Comprehensive TDD Kata

I hope you will realise most if not all of the attributes, that I mentioned in my previous article, that makes TDD worth a try.

I apologise for the lengthy article but please bare with me as I try to bring across TDD concepts.

Introduction

As a measure to beef up application security, your business owner has asked you to implement a password compliance component that satisfies the criteria detailed below.

Acceptance Criteria

If a user enters a non-compliant password, the component should return a message notifying the user of what is wrong with the given password. The returned message should be similar to the corresponding description in the acceptance criteria.

HINT:

This can be represented by the following regular expression [^a-zA-Z0–9]

The basic premise of TDD is that you write a test before writing the code that actually provides the implementation, and then you refactor that implementation as needed.

When TDD practitioners need to implement a feature, they first write a failing test that describes, or specifies, that feature. Next, they write just enough code to make the test pass. Finally, they refactor the code to help ensure that it will be easy to maintain.

TDD 3-phase cycle. [2]

Let’s see how TDD techniques can be applied to fulfill the abovementioned requirements. The solution below is coded in Java. The Unit tests are implemented in JUnit and Spock.

Password Validator component

NOTE: I have simplified the implementation by including the Data Transfer Objects (DTOs) in this project. Best practice would dictate that the DTOs are auto-generated in a separate project and included as a dependency in the client project.

The password should have at least one uppercase character

Executing the test cases at this stage, as expected, will result in a failing test case.

No uppercase failing test case

No Uppercase Implementation

Next, write the least amount of code to make the test case pass.

With the implementation above, executing the test case results in a passing test case.

No uppercase passing test case

Refactor No Uppercase Implementation

The isUppercaseCharacterPresent variable can be extracted into a method.

NOTE: Run the test to make sure it still passes.

The password should have at least one lowercase character

Do you notice the code duplication from the 2 test cases? This will be addressed later using the Parameterized Test Pattern.

No lowercase failing test case

No Lower Case Implementation

No lowercase passing test case

Looking at these 2 methods they take in a parameter, perform an action on it, and return true or false depending on the values in the given parameter.

Java 8 comes with several new functional interfaces in the package java.util.function. One of the interfaces is a Predicate. This interface returns a boolean value based on an input of type T.

NOTE: Run the tests and make sure they still pass.

Let’s update the PasswordValidator component diagram to represent the current implementation.

Password Validator component update

The 2 Predicates can be pushed out and the variables in question will be abstracted into a collection on the PasswordValidator component.

This design needs to be refined before the code gets to a workable state.

To cater for the Regular Expressions and Notification Messages, there is a need for a class that derives from a Predicate that will take into consideration both of these concerns. This is all addressed in the diagram below.

Let’s go ahead and update the code.

NOTE: For simplicity, the rules are hard-coded into the password validation component. In an actual implementation, it is best practice to provide the rules as configuration. I will leave that as an exercise for the reader.

NOTE: Run the tests and make sure they still pass.

Use the following Java 8 idioms to refactor the password validator component:

NOTE: Run the tests and make sure they still pass.

Tabular Data Input with Spock

Spock enables you to directly embed a table as-is inside your Groovy code. The following code snippet shows how this is done in the current context.

The key point of this unit test is the where: label (in addition to the usual given-then-when labels) that holds a definition of all inputs/outputs used in the other blocks. In the where: block of this Spock test, I copied verbatim the password validation scenarios into the table. The || notation is used to split the inputs from the outputs. The @Unroll annotation “unrolls” the test scenarios and presents them to the test runner as individual tests.

NOTE: Run the tests and make sure they still pass.

After this slight but necessary detour, I can now proceed and define the remainder of the test scenarios and their corresponding implementations. It should be downhill from here.

The password should have at least one digit

No digit failing test case

No Digit Implementation

No digit passing test case

The password should have at least one special character

No Special Character Implementation

No special character passing test case

The password should at least be 12 characters long

Password Length Implementation

Password length passing test case

The password should NOT have any whitespace

Password with whitespace failing test case

Password with Whitespace Implementation

Password with whitespace passing test case

Happy Day Scenario

Because the password meets all the previous criteria, the test cases pass without the need to implement any code.

Happy day scenario

Password violates multiple of the Password Compliance Rules

There is no need to implement any code as the implementation already caters for these scenarios.

Password with multiple violation test case

Thank you for taking the time to follow along. This has been an in-depth look at TDD in practice. I hope you have learnt something that will help you understand TDD better.

References

[1] TDD Katas — JAVING

[2] BDD in Action, Manning Publication Co, 2015 — John Ferguson Smart

Add a comment

Related posts:

Improve the Sales Experience on Your Website

Here we introduce 7 ways to improve the sales experience on your website. The sales experience on your website is critical to gathering leads or even to get your visitors converting to paid customers…

Smart Strategies for Building Wealth

One of the most important things you can do to generate wealth is to use your money in smart ways that leverage it. You can make more investments than you would be able to with just your own money if…

Overcome Daily Struggles By Thinking Focused Thoughts

Overcome daily struggles by doing the opposite . Focus on the big thoughts. Thinking micro has led to stress, therefore think macro to shift perspective.