Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Practical Test-Driven Development using C# 7
Practical Test-Driven Development using C# 7

Practical Test-Driven Development using C# 7: Unleash the power of TDD by implementing real world examples under .NET environment and JavaScript

eBook
€8.99 €32.99
Paperback
€41.99
Subscription
Free Trial
Renews at €18.99p/m

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Table of content icon View table of contents Preview book icon Preview Book

Practical Test-Driven Development using C# 7

Why TDD is Important

You've picked up this book because you want to learn more about Test-Driven Development (TDD). Maybe you've heard the term before. Perhaps you've known software developers who write unit tests and want to learn more. We'll introduce you to the terms, the structure, and the ideology around TDD. By the end of this book, you'll have sufficient knowledge to re-enter the world as a Test-Driven Developer and feel confident about using your skills throughout your long and prosperous career.

Why this book? Certainly, there are many other books on the topic of TDD. We have written this book with the hope that it provides you, the reader, with low-level insight into the mindset we use when doing TDD. We also hope that this book provides an updated view of some of the concepts and lessons we have learned while doing TDD over the last 10 years. 

So, why is TDD so important? As more businesses and industries rely on software solutions, it's increasingly important that those solutions be robust and error-free. The cheaper and more consistent, they are the better. Applications developed with TDD in mind are inherently more testable, easier to maintain, and demonstrate a certain level of correctness not easily achieved otherwise.

In this chapter, we will gain an understanding of:

  • Defining TDD and exploring the basics
  • Creating our first tests in C# and JavaScript
  • Exploring the basic steps of Red, Green, Refactor
  • Growing complexity through tests

First, a little background

It's possible that you've had some exposure to unit tests in your career. It's highly likely that you've written a test or two. Many developers, unfortunately, haven't had the opportunity to experience the joys of Test-Driven Development.

John's story on TDD

I was first introduced to TDD about five years ago. I was interviewing for a lead developer position for a small startup. During the interview process, the CTO mentioned that the development team was practicing TDD. I informed him that I didn't have any practical TDD experience, but that I was sure I could adapt.

In all honesty, I was bit nervous. Up to that point, I had never even written a single unit test! What had I gotten myself into? An offer was extended and I accepted. Once I joined the small company I was told that, while TDD was the goal, they weren't quite there yet. Phew; crisis averted. However, I was still intrigued. It wasn't until a few months later that the team delved into the world of TDD, and the rest, as they say, is history.

Clayton's story on TDD

My introduction to TDD is a little different from John's. I have been writing code since I was in middle school in the early 1990s. From then until 2010, I always struggled with writing applications that didn't require serious architectural changes when new requirements were introduced. In 2010, I finally got fed up with the constant rewrites and began researching tools and techniques to help me with my problem. I quickly found TekPub, an e-learning site that was, at the time, owned and operated by Rob Conery. Through TekPub I began learning the SOLID principles and TDD. After banging my head against the wall for close to six months, I started to grasp what TDD was and how I could use those principles. Coupled with the SOLID principles, TDD helped me to write easy to understand code that was flexible enough to stand up to any requirements the business could throw at me. I eventually ended up at the same company where John was employed and worked with him and, as he said, the rest is history.

The SOLID principles, which will be explained in detail later, are guiding principles that help produce clean, maintainable, and flexible code. They help reduce rigidity, fragility, and complexity. Generally thought of as object-oriented principles, I have found them to be applicable in all coding paradigms.

So, what is TDD?

Searching online, you will certainly find that TDD is an acronym for Test-Driven Development. In fact, the title of this book will tell you that. We, however, use a slightly more meaningful definition. So, what is TDD? In the simplest terms, TDD is an approach to software development that is intended to reduce errors and enable flexibility within the application. If done correctly, TDD is a building block for rapid, accurate, and fearless application development. 

Test-Driven Development is a means of letting your tests drive the design of the system. What does that mean, exactly? It means that you mustn't start with a solution in mind, you must let your tests drive the code being written. This helps minimize needless complexity and avoid over-architected solutions. The rules of Test-Driven Development

Staunch proponents of TDD dictate that you may not write a single line of production code without writing a failing unit test, and failing to compile is a failure. This means that you write a simple test, watch it fail, then write some code to make it pass. The system slowly evolves as the tests and the production application grow in functionality.

TDD is not about testing, it's about design.

Many would argue that TDD is about testing, and by extension, about test coverage of an application. While these are great side-effects of TDD, they are not the driving force behind the practice.

Additionally, if code coverage and metrics become the goal, then there is a risk that developers will introduce meaningless tests just to inflate the numbers. Perhaps it is less a risk and more a guarantee that this will happen. Let delivered functionality and happy customers be the metrics with which you measure success.

TDD is about design. Through TDD, an application will grow in functionality without introducing needless complexity. It's incredibly difficult to introduce complexity if you write small tests and only enough production code to make the test pass. Refactoring, modifying the structure of the code without adding or changing behavior,  should not introduce complexity, either.

An approach to TDD 

TDD is also referred to as Test First Development. In both names, the key aspect is that the test must be written before the application code. Robert C. Martin, affectionately called "Uncle Bob" by the developer community, has created The Three Laws of TDD. They are as follows: 

  1. You are not allowed to write any production code unless it is to make a failing unit test pass
  2. You are not allowed to write any more of a unit test than is sufficient to fail, and compilation failures are failures
  3. You are not allowed to write any more production code than is sufficient to pass the one failing unit test

You can learn more about these laws at http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd 

By following these rules, you will ensure that you have a very tight feedback loop between your test code and your production code. One of the main components of Agile software development is working to reduce the feedback cycle. A small feedback cycle allows the project to make a course correction at the first sign of trouble. The same applies to the testing feedback cycle. The smaller you can make your tests, the better the end result will be. 

For a video on Agile, check out Getting Started with Agile by Martin Esposito and Massimo Fascinari (https://www.packtpub.com/application-development/getting-started-agile-video).

An alternative approach 

The original approach to TDD has caused some confusion over the years. The problem is that the principles and approaches just weren't structured enough. In 2006, Dan North wrote an article in Better Software magazine (https://www.stickyminds.com/better-software-magazine/behavior-modification). The purpose of the article was to clear up some of this confusion and help to reduce the pitfalls that developers fell into while learning the TDD process. This new approach to TDD is called Behavior Driven Development (BDD). BDD provides a structure for testing, and a means of communicating between business requirements and unit tests, that is almost seamless. 

The process

It's difficult to start any journey without a goal in mind. There are a few tips and tricks that can be used to help get you started in TDD. The first is red, green, refactor.

Red, green, and refactor

We already discussed writing a failing test before writing production code. The goal is to build the system slowly through a series of tiny improvements. This is often referred to as red, green, refactor. We write a small test (red), then we make it pass by writing some production code (green), then we refactor our code (refactor) before we start the process again.

Many TDD practitioners advocate an It Exists test first. This will help determine that your environment is set up properly and you won't receive false positives. If you write an It Exists test and don't receive a failure right off the bat, you know something is wrong. Once you receive your first failure, you're safe to create the class, method, or function under test. This will also ensure that you don't dive in too deeply right off the bat with lines and lines of code before you're sure your system is working properly.

Once you have your first failure and the first working example, it's time to grow the application, slowly. Choose the next most interesting step and write a failing test to cover this step.

At each iteration, you should pause and evaluate whether there is any cleanup that can happen. Can you simplify a code block? Perhaps a more descriptive variable name is in order? Can any sins committed in the code be corrected, safely, at this time? It's important that you evaluate both the production code and the test suite. Both should be clean, accurate, and maintainable. After all, if it's such a mess that no one would be able to make head or tail of it, what good is the code?

Coder's block

TDD will also help you avoid what writers often call writer's block and what we're calling coder's block. Coder's block happens when you sit down at the keyboard in an attempt to solve a problem but don't know where to begin. We begin at the beginning. Write the easiest, simplest test you can imagine. Write It Exists.   

Why should we care?

We're professionals. We want to do a good job. We feel bad if someone finds fault with our code. If QA finds a bug, it makes us sad. If a user of our system encounters an error, we may cry. We should strive to deliver quality, error-free code and a fully functional, feature-rich application.

We're also lazy, but it's the good kind of lazy. We don't want to have to run the entire application just to validate that a simple function returns the proper value.

Arguments against TDD

There are arguments against TDD, some valid and some not. It's quite possible that you've heard some of them before, and likely that you've repeated some of these yourself. 

Testing takes time

Of course, testing takes time. Writing unit tests takes time. Adhering to the red, green, refactor cycle of TDD does take time. But, how else do you check your work if not through tests?

Do you validate that the code you wrote works? How do you do this without tests? Do you manually run the application? How long does that take? Are there conditional scenarios that you need to account for within the application? Do you have to set up those scenarios while manually testing the application? Do you skip some and just trust that they work?

What about regression testing? What if you make a change a day, a week, or a month later? Do you have to manually regression-test the entire application? What if someone else makes a change? Do you trust that they were also as thorough in their testing, as I’m sure you are?

How much time would you save if your code were covered by a test suite that you could run at the click of a button?

Testing is expensive

By writing tests, you're effectively doubling the amount of code you're writing, right? Well, yes and no. Okay, in an extreme case, you might approach double the code. Again, in an extreme case.

Don't make tests a line item.

In some instances, consulting companies have written unit tests into a contract with a line item and dollar amount attached. Inevitably, this allows the customer the chance to argue to have this line item removed, thus saving them money. This is absolutely the wrong approach. Testing will be done, period, whether manually by the developer running the application to validate her work, by a QA tester, or by an automated suite of tests. Testing is not a line item that can be negotiated or removed (yikes!).

You would never buy an automobile that didn’t pass quality control. Light bulbs must pass inspection. A client, customer, or company will never, ever, save money by foregoing testing. The question becomes, do you write the tests early, while the code is being authored, or manually, at a later date?

Testing is difficult

Testing can be difficult. This is especially true with an application that was not written with testability in mind. If you have static methods and implementations using concrete references scattered throughout your code, you will have difficulty adding tests at a later date.

We don't know how

I don't know how to test is really the only acceptable answer, assuming it is quickly followed by, but I'm willing to learn. We're developers. We're the experts in the room. We're paid to know the answers. It's scary to admit that we don't know something. It's even scarier to start something new. Rest assured, it will be OK. Once you get the hang of TDD, you’ll wonder how you managed before. You'll refer to those times as the dark ages, before the discovery of the wheel.

Arguments in favor of TDD

What we would like to focus on here are the positives, the arguments in favor of TDD.

Reduces the effort of manual testing

We already mentioned that we, as professionals, will not ship anything without first determining that it works. Throwing something over the wall to QA, to our users, or to the general public and hoping that it all works as expected just isn't how we do business. We will verify that our code and our applications work as expected. In the beginning, while the application is small and has little functionality, we can manually test everything we can think of. But, as the application grows in size and complexity, it just isn't feasible for developers or anyone else to manually test an entire application. It’s too time-consuming and costly to do this manually. We can save ourselves time and our clients and companies money by automating our testing. We can do so quite easily, from the beginning, through TDD.

Reduces bug count

As our application grows, so do our tests. Or shall we say, our test suite has grown, and by making our tests pass, our application has grown. As both have grown, we've covered the happy path (for example: 2 + 2 = 4) as well as potential failures (for example: 2 + banana = exception). If the method or function under test can accept an input parameter, there is a potential for failure. You can reduce the potential for unexpected behavior, bugs, and exceptions by writing code to guard against these scenarios. As you write tests to express potential failures, your production code will inherently become more robust and less prone to errors. If a bug does slip by and make it to QA, or even to a production environment, then it's easy enough to add a new test to cover the newly discovered defect.

The added benefit of approaching bugs in this fashion is that the same bug rarely crops up again at some later date, as the new tests guard against this. If the same bug does appear, you know that, while the same result has happened, the bug occurred in a new and different way. With the addition of another test to cover this new scenario, this will likely be the last time you see the same old bug.

Ensures some level of correctness

With a comprehensive suite of tests, you can demonstrate some level of correctness. At some point, someone somewhere will ask you whether you are done. How will you show that you have added the desired functionality to an application?

Removes the fear of refactoring

Let's face it, we've all worked on legacy applications that we were scared to touch. Imagine if the class you were tasked with modifying were covered by a comprehensive set of unit tests. Picture how easy it would be to make a change and know that all was right with the world because all of the unit tests still passed.

A better architecture 

Writing unit tests tends to push your code towards a decoupled design. Tightly coupled code quickly becomes burdensome to test, and so, to make one's life easier, a Test-Driven Developer will begin to decouple the code. Decoupled code is easier to swap in and out, which means that, instead of modifying a tangled knot of production code, often all that a developer needs to do to make the necessary changes is swap out a subcomponent with a new module of code. 

Faster development 

It may not feel like it at first (in fact, it definitely will not feel like it at first), but writing unit tests is an excellent way to speed up development. Traditionally, a developer receives requirements from the business, sits down, and begins shooting lightning from her fingertips, allowing the code to pour out until an executable application has been written. Before TDD, a developer would write code for a few minutes and then launch the application so that she could see if the code worked or not. When a mistake was found, the developer would fix it and launch the application once again to check whether the fix worked. Often, a developer would find that her fix had broken something else and would then have to chase down what she had broken and write another fix. The process described is likely one that you and every other developer in the world are familiar with. Imagine how much time you have lost fixing bugs that you found while doing developer testing. This does not even include the bugs found by QA or in production by the customer. 

Now, let's picture another scenario. After learning TDD, when we receive requirements from the business, we quickly convert those requirements directly into tests. As each test passes we know that, as per the requirements, our code does exactly what has been asked of it. We might discover some edge cases along the way and create tests to ensure the code has the correct behavior for each one. It would be rare to discover that a test is failing after having made it pass. But, when we do cause a test to fail, we can quickly fix it by using the undo command in our editor. This allows us to hardly even run the application until we are ready to submit our changes to QA and the business. Still, we try to verify that the application behaves as required before submitting, but now we don't do this manually, every few minutes. Instead, let your unit tests verify your code each time you save a file. 

Different types of test

Over the course of this book, we will be leaning towards a particular style of testing, but it is important to understand the terminology that others will use so that you can relate when they speak about a certain type of test. 

Unit tests 

Let's jump right in with the most misused and least understood test type. In Kent Beck's book, Test-Driven Development by Example, he defines a unit test as simply a test that runs in isolation from the other tests. All that means is that for a test to be a unit test, all that has to happen is that the test must not be affected by the side-effects of the other tests. Some common misconceptions are that a unit test must not hit the database, or that it must not use code outside the method or function being tested. These simply aren't true. We tend to draw the line in our testing at third-party interactions. Any time that your tests will be accessing code that is outside the application you are writing, you should abstract that interaction. We do this for maximum flexibility in the design of the test, not because it wouldn't be a unit test. It is the opinion of some that unit tests are the only tests that should ever be written. This is based on the original definition, and not on the common usage of the term. 

Acceptance tests 

Tests that are directly affected by business requirements, such as those suggested in BDD, are generally referred to as acceptance tests. These tests are at the outermost limit of the application and exercise a large swathe of your code. To reduce the coupling of tests and production code, you could write this style of test almost exclusively. Our opinion is, if a result cannot be observed outside the application, then it is not valuable as a test. 

Integration tests 

Integration tests are those that integrate with an external system. For instance, a test that interacts with a database would be considered an integration test. The external system doesn't have to be a third-party product; however, sometimes, the external system is just an imported library that was developed independently from the application you are working on but is still considered in-house software. Another example that most don't consider is interactions with the system or language framework. You could consider any test that uses the functions of C#'s DateTime object to be an integration test. 

End to end tests 

These tests validate the entire configuration and usage of your application. Starting from the user interface, an end to end test will programmatically click a button or fill out a form. The UI will call into the business logic of the application, executing all the way down to the data source for the application. These tests serve the purpose of ensuring that all external systems are configured and operating correctly. 

Quantity of each test type 

Many developers ask the question: How many of each type of test should be used? Every test should be a unit test, as per Kent Beck's definition. We will cover variations on testing later that will have some impact on specific quantities of each type; but, generally, you might expect an application to have very few end to end tests, slightly more integration tests, and to consist mostly of acceptance tests. 

Parts of a unit test

The simplest way to get started and ensure that you have human-readable code is to structure your tests using Arrange, Act, and Assert.

Arrange

Also known as the context of a unit test, Arrange includes anything that exists as a prerequisite of the test. This includes everything from parameter values, stored in variables to improve readability, all the way to configuring values in a mock database to be injected into your application when the test is run.

For more information on Mocking, see Chapter 3Setting Up the JavaScript Environment, the Abstract Third Party Software and Test Double Types sections.

Act

An action, as part of a unit test, is simply the piece of production code that is being tested. Usually, this is a single method or function in your code. Each test should have only a single action. Having more than one action will lead to messier tests and less certainty about where the code should change to make the test pass.

Assert

The result, or assertion (the expected result), is exactly what it sounds like. If you expect that the method being tested will return a 3, then you write an assertion that validates that expectation. The Single Assert Rule states that there should be only one assertion made per test. This does not mean that you can only assert once; instead, it means that your assertions should only confirm one logical expectation. As a quick example, you might have a method that returns a list of items after applying a filter. After setting up the test context, calling the method will result in a list of only one item, and that item will match the filter that we have defined. In this case, you will have a programmatic assert for the count of items in the list and one programmatic assert for the filter criterion we are testing. 

Requirements 

While this book is not about business analysis or requirement generation, requirements will have a huge impact on your ability to effectively test-drive an application. We will be providing requirements for this book in a format that lends itself very well to high-quality tests. We will also cover some scenarios where the requirements are less than optimal, but for most of this book the requirements have been labored over to ensure a high-quality definition of the systems we are testing. 

Why are they important? 

We firmly believe that quality requirements are essential to a well-developed solution. The requirements inform the tests and the tests shape the code. This axiom means that with poor requirements, the application will result in a lower quality architecture and overall design. With haphazard requirements, the resulting tests and application will be chaotic and poorly factored. On the bright side, even poorly thought out or written requirements aren't the death knoll for your code. It is our responsibility, as professional software developers, to correct bad requirements. It is our task to ask questions that will lead to better requirements.  

User stories 

User stories are commonly used in Agile software development for requirement definitions. The format for a user story is fairly simple and consists of three parts: Role, Request, and Reason.  

As a <Role> 
I want <Request>
So that <Reason>

Role 

The role of the user story can provide a lot of information. When specifying the role, we have the ability to imply the capabilities of the user. Can the user access certain functionalities, or are they physically impaired in such a way that requires an alternate form of interaction with the system? We can also communicate the user's mindset. Having a new user could have an impact on the design of the user interface, in contrast to what an experienced user might expect. The role can be a generic user, a specific role, a persona, or a specific user. 

Generic users are probably the most used and, at the same time, the least useful. Having a story that provides no insight into the user limits our decision making for this story by not restricting our context. If possible, ask your business analyst or product owner for a more specific definition of who the requirement is for. 

Defining a specific role, such as Admin, User, or Guest, can be very helpful. Specific roles provide user capability information. With a specific role, we can determine if a user should even be allowed into the section of the application we are defining functionality for. It is possible that a user story will cause the modification of a user's rights within the system, simply because we specified a role instead of a generic user. 

Using a persona is the most telling of the wide-reaching role types. A persona is a full definition of an imaginary user. It includes a name, any important physical attributes, preferences, familiarity with the subject of the application, familiarity with computers, and anything else that might have an impact on the imaginary user's interactions with the software. By having all this information, we can start to roleplay the user's actions within the system. We can start to make assumptions or decisions about how that user would approach or feel about a suggested feature and we can design the user interface with that user in mind. 

Request 

The request portion of the user story is fairly simple. We should have a single feature or a small addition to functionality that is being requested. Generally, the request is too large if it includes any joining words, such as and or or

Reason 

The reason is where the business need is stated. This is the opportunity to explain how the feature will add value to the company. By connecting the reason to the role, we can enhance the impact of the feature's usefulness. 

A complete user story might look like the following:

As a Conference Speaker 
I want to search for nearby conferences by open submission date
So that I may plan the submission of my talks

Gherkin 

Gherkin is a style of requirements definitions that is often used for acceptance criteria. We can turn these requirements directly into code, and QA can turn them directly into test cases. The Gherkin format is generally associated with BDD, and it is used in Dan North's original article on the subject.  

The Gherkin format is just as simple as the user story format. It consists of three parts: Given, When, and Then

Given <Context> 
And Given <More Context>
When <Action>
Then <Result>
And Then <More Results>

Givens 

Because the Gherkin format is fairly simple, givens are broken out to one per contextual criterion. As part of specifying the context, we want to see any and all preconditions of this scenario. Is the user logged in? Does the user have any special rights? Does this scenario require any settings to be put into force before execution? Has the user provided any input on this scenario? One more thing to consider is that there should only be a small number of givens.

The more givens that are present in a scenario, the more likely it is that the scenario is too big or that the givens can somehow be logically grouped to reduce the count. 

When we start writing our tests, a Given is analogous to the Arrange section of a test.  

When 

The when is the action taken by the user. There should be one action and only one action. This action will depend on the context defined by the Given and output the result expected by the Then. In our applications, this is equivalent to a function or method call. 

When we start writing our tests, a When is analogous to the Act section of a test.

Then 

Thens equate to the output of the action. Thens describe what can be verified and tested from the output of a method or function, not only by developers but also by QA.  Just like with the Givens, we want our Thens to be singular in their expectation. Also like Givens, if we find too many Thens, it is either a sign that this scenario is getting too big, or that we are over-specifying our expectations. 

When we start writing our tests, a Then is analogous to the Assert section of a test.

Complete acceptance criteria based on the user story presented earlier might look like the following:

Given I am a conference speaker 
And Given a search radius of 25 miles
And Given an open submission start date
And Given an open submission end date
When I search for conferences
Then I receive only conferences within 25 miles of my location
And Then I receive only conferences that are open for submission within the specified date range

Just like in life, not everything in this book is going to be perfect. Do you see anything wrong with the preceding acceptance criteria? Go on and take a few minutes to examine it; we'll wait.  

If you've given up, we'll tell you. The above acceptance criteria are just too long. There are too many Givens and too many Thens. How did this happen? How could we have created such a mistake? When we wrote the user story, we accidentally included too much information for the reason that we specified. If you go back and look at the user story, you will see that we threw nearby in the request. Adding nearby seemed harmless; it even seemed more correct. I, as the user, wasn't so interested in traveling too far for my speaking engagements.  

When you start to see user stories or acceptance criteria getting out of hand like this, it is your responsibility to speak with the business analyst or product owner and work with them to reduce the scope of the requirements. In this case, we can extract two user stories and several acceptance criteria. 

Here is a full example of the requirements we have been examining:

As a conference speaker 
I want to search for nearby conferences
So that I may plan the submission of my talks
Given I am a conference speaker
And Given search radius of five miles
When I search for conferences
Then I receive only conferences within five miles of my location
Given I am a conference speaker
And Given search radius of 10 miles
When I search for conferences
Then I receive only conferences within 10 miles of my location
Given I am a conference speaker
And Given search radius of 25 miles
When I search for conferences
Then I receive only conferences within 25 miles of my location

As a conference speaker
I want to search for conferences by open submission date
So that I may plan the submission of my talks
Given I am a conference speaker
And Given open submission start and end dates
When I search for conferences
Then I receive only conferences that are open for submission within the specified date range
Given I am a conference speaker
And Given an open submission start date
And Given an empty open submission end date
When I search for conferences
Then an INVALID_DATE_RANGE error occurs for open submission date
Given I am a conference speaker
And Given an empty open submission start date
And Given an open submission end date
When I search for conferences
Then an INVALID_DATE_RANGE error occurs for open submission date

One thing that we have not discussed is the approach to the content of the user stories and acceptance criteria. It is our belief that requirements should be as agnostic about the user interface and data storage mechanism as possible. For that reason, in the requirement examples, you'll notice that there is no reference to any kind of buttons, tables, modals/popups, clicking, or typing. For all we know, this application is running in a Virtual Reality Helmet with a Natural User Interface. Then again, it could be running as a RESTful web API, or maybe a phone application. The requirements should specify the system interactions, not the deployment environment. 

In software development, it is everyone's responsibility to ensure high-quality requirements. If you find the requirements you have received to be too large, vague, user interface-dependent, or just unhelpful, it is your responsibility to work with your business analyst or product owner to make the requirements better and ready for development and QA. 

Our first tests in C#

Have you ever created a new MVC project in Visual Studio? Have you noticed the checkbox towards the bottom of the dialog box? Have you ever selected, Create Unit Test Project? The tests created with this Unit Test Project are largely of little use. They do little more than validate that the default MVC controllers return the proper type. This is perhaps one step beyond, ItExists. Let's look at the first set of tests created for us:

using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SampleApplication.Controllers;

namespace SampleApplication.Tests.Controllers
{
[TestClass]
public class HomeControllerTest
{
[TestMethod]
public void Index()
{
// Arrange
HomeController controller = new HomeController();

// Act
ViewResult result = controller.Index() as ViewResult;

// Assert
Assert.IsNotNull(result);
}

[TestMethod]
public void About()
{
// Arrange
HomeController controller = new HomeController();

// Act
ViewResult result = controller.About() as ViewResult;

// Assert
Assert.AreEqual("Your application…", result.ViewBag.Message);
}

[TestMethod]
public void Contact()
{
// Arrange
HomeController controller = new HomeController();

// Act
ViewResult result = controller.Contact() as ViewResult;

// Assert
Assert.IsNotNull(result);
}
}
}

Here, we can see the basics of a test class, and the test cases contained within. Out of the box, Visual Studio ships with MSTest, which is what we can see here. The test class must be decorated with the [TestClass] attribute. Individual tests must likewise also be decorated with the [TestMethod] attribute. This allows the test runner to determine which tests to execute. We'll cover these attributes and more in future chapters. Other testing frameworks use similar approaches that we'll discuss later, as well.

For now, we can see that the HomeController is being tested. Each of the public methods has a single test, for which you may want to create additional tests and/or extract tests to separate files in the future. Later we'll be covering options and best practices to help you arrange your files in a much more manageable fashion. All of this should be part of your refactor step in your red, green, refactor cycle.

Growing the application with tests

Perhaps you want to accept a parameter for one of your endpoints. Maybe you will take a visitor's name to display a friendly greeting. Let's take a look at how we might make that happen:

[TestMethod]
public void ItTakesOptionalName()
{
// Arrange
HomeController controller = new HomeController();

// Act
ViewResult result = controller.About("") as ViewResult;

// Assert
Assert.AreEqual("Your application description page.", result.ViewBag.Message);
}

We start by creating a test to allow for the About method to accept an optional string parameter. We're starting with the idea that the parameter is optional since we don't want to break any existing tests. Let's see the modified method:

public ActionResult About(string name = default(string))
{
ViewBag.Message = "Your application description page.";
return View();
}

Now, let's use the name parameter and just append it to our ViewBag.Message. Wait, not the controller. We need a new test first:

[TestMethod]
public void ItReturnsNameInMessage()
{
// Arrange
HomeController controller = new HomeController();

// Act
ViewResult result = controller.About("Fred") as ViewResult;

// Assert
Assert.AreEqual("Your application description page.Fred", result.ViewBag.Message);
}

And now we'll make this test pass:

public ActionResult About(string name = default(string))
{
ViewBag.Message = $"Your application description page.{name}";
return View();
}

Our first tests in JavaScript

To get the ball rolling in JavaScript, we are going to write a Simple Calculator class. Our calculator only has the requirement to add or subtract a single set of numbers. Much of the code you write in TDD will start very simply, just like this example:

import { expect } from 'chai'

class SimpleCalc {
add(a, b) {
return a + b;
}

subtract(a, b) {
return a - b;
}
}

describe('Simple Calculator', () => {
"use strict";

it('exists', () => {
// arrange
// act
// assert
expect(SimpleCalc).to.exist;
});

describe('add function', () => {
it('exists', () => {
// arrange
let calc;

// act
calc = new SimpleCalc();

// assert
expect(calc.add).to.exist;
});

it('adds two numbers', () => {
// arrange
let calc = new SimpleCalc();

// act
let result = calc.add(1, 2);

// assert
expect(result).to.equal(3);
});
});

describe('subtract function', () => {
it('exists', () => {
// arrange
let calc;

// act
calc = new SimpleCalc();

// assert
expect(calc.subtract).to.exist;
});

it('subtracts two numbers', () => {
// arrange
let calc = new SimpleCalc();

// act
let result = calc.subtract(3, 2);

// assert
expect(result).to.equal(1);
});
});
});

If the preceding code doesn't make sense right now, don't worry; this is only intended to be a quick example of some working test code. The testing framework used here is Mocha, and the assertion library used is chai. In the JavaScript community, most testing frameworks are built with BDD in mind. Each described in the code sample above represents a scenario or a higher-level requirements abstraction; whereas, each it represents a specific test. Within the tests, the only required element is the expect, without which the test will not deliver a valuable result.

Continuing this example, say that we receive a requirement that the add and subtract methods must be allowed to chain. How would we tackle that requirement? There are many ways, but in this case, I think I would like to do a quick redesign and then add some new tests. First, we will do the redesign, again driven by tests.

By placing only on a describe or a test, we can isolate that describe/test. In this case, we want to isolate our add tests and begin making our change here:

it.only('adds two numbers', () => {
// arrange
let calc = new SimpleCalc(1);

// act
let result = calc.add(2).result;

// assert
expect(result).to.equal(3);
});

Previously, we have changed the test to use a constructor that takes a number. We have also reduced the number of parameters of the add function to a single parameter. Lastly, we have added a result value that must be used to evaluate the result of adding.

The test will fail because it does not use the same interface as the class, so now we must make a change to the class:

class SimpleCalc {
constructor(value) {
this._startingPoint = value || 0;
}

add(value) {
return new SimpleCalc(this._startingPoint + value);
}
...
get result() {
return this._startingPoint;
}
}

This change should cause our test to pass. Now, it's time to make a similar change for the subtract method. First, remove the only that was placed in the previous example:

it('subtracts two numbers', () => {
// arrange
let calc = new SimpleCalc(3);

// act
let result = calc.subtract(2).result;

// assert
expect(result).to.equal(1);
});

Now for the appropriate change in the class:

subtract(value) {
return new SimpleCalc(this._startingPoint – value);
}

Out tests now pass again. The next thing we should do is create a test that verifies everything works together. We will leave this test up to you as an exercise, should you want to attempt it.

Why does it matter?

So, why does all this matter? Why write more code than we have to? Because it's worth it. And to be honest, most of the time it isn't more code. As you take the time to grow your application with tests, simple solutions are produced. Simple solutions are almost always less code than the slick solution you might have come up with otherwise. And inevitably, slick solutions are error-prone, difficult to maintain, and often just plain wrong.

Summary

If you didn't before, you should now have a good idea of what TDD is and why it is important. You have been exposed to unit tests in C# and JavaScript and how writing tests first can help grow an application.

As we continue, we'll learn more about TDD. We'll explore what it means to write testable code.

In Chapter 2, Setting Up the .NET Test Environment, we'll set up your development environment and explore additional aspects of a unit test.

Left arrow icon Right arrow icon

Key benefits

  • • Develop a thorough understanding of TDD and how it can help you develop simpler applications with no defects using C# and JavaScript
  • • Adapt to the mindset of writing tests before code by incorporating business goals, code manageability, and other factors
  • • Make all your software units and modules pass tests by analyzing failed tests and refactoring code as and when required

Description

Test-Driven Development (TDD) is a methodology that helps you to write as little as code as possible to satisfy software requirements, and ensures that what you've written does what it's supposed to do. If you're looking for a practical resource on Test-Driven Development this is the book for you. You've found a practical end-to-end guide that will help you implement Test-Driven Techniques for your software development projects. You will learn from industry standard patterns and practices, and shift from a conventional approach to a modern and efficient software testing approach in C# and JavaScript. This book starts with the basics of TDD and the components of a simple unit test. Then we look at setting up the testing framework so that you can easily run your tests in your development environment. You will then see the importance of defining and testing boundaries, abstracting away third-party code (including the .NET Framework), and working with different types of test double such as spies, mocks, and fakes. Moving on, you will learn how to think like a TDD developer when it comes to application development. Next, you'll focus on writing tests for new/changing requirements and covering newly discovered bugs, along with how to test JavaScript applications and perform integration testing. You’ll also learn how to identify code that is inherently un-testable, and identify some of the major problems with legacy applications that weren’t written with testability in mind. By the end of the book, you’ll have all the TDD skills you'll need and you’ll be able to re-enter the world as a TDD expert!

Who is this book for?

This book is for software developers with a basic knowledge of Test Driven Development (TDD) who want a thorough understanding of how TDD can benefit them and the applications they produce. The examples in this book are in C#, and you will need a basic understanding of C# to work through these examples.

What you will learn

  • • The core concepts of TDD
  • • Testing in action with a real-world case study in C# and JavaScript using React
  • • Writing proper Unit Tests and testable code for your application
  • • Using different types of test double such as stubs, spies, and mocks
  • • Growing an application guided by tests
  • • Exploring new developments on a green-field application
  • • Mitigating the problems associated with writing tests for legacy applications
  • • Modifying a legacy application to make it testable
Estimated delivery fee Deliver to Malta

Premium delivery 7 - 10 business days

€32.95
(Includes tracking information)

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Feb 15, 2018
Length: 442 pages
Edition : 1st
Language : English
ISBN-13 : 9781788398787
Languages :
Tools :

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Estimated delivery fee Deliver to Malta

Premium delivery 7 - 10 business days

€32.95
(Includes tracking information)

Product Details

Publication date : Feb 15, 2018
Length: 442 pages
Edition : 1st
Language : English
ISBN-13 : 9781788398787
Languages :
Tools :

Packt Subscriptions

See our plans and pricing
Modal Close icon
€18.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
€189.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts
€264.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total 134.97
C# 7.1 and .NET Core 2.0 ??? Modern Cross-Platform Development
€59.99
Learn C# in 7 days
€32.99
Practical Test-Driven Development using C# 7
€41.99
Total 134.97 Stars icon
Banner background image

Table of Contents

15 Chapters
Why TDD is Important Chevron down icon Chevron up icon
Setting Up the .NET Test Environment Chevron down icon Chevron up icon
Setting Up a JavaScript Environment Chevron down icon Chevron up icon
What to Know Before Getting Started Chevron down icon Chevron up icon
Tabula Rasa – Approaching an Application with TDD in Mind Chevron down icon Chevron up icon
Approaching the Problem Chevron down icon Chevron up icon
Test-Driving C# Applications Chevron down icon Chevron up icon
Abstract Away Problems Chevron down icon Chevron up icon
Testing JavaScript Applications Chevron down icon Chevron up icon
Exploring Integrations Chevron down icon Chevron up icon
Changes in Requirements Chevron down icon Chevron up icon
The Legacy Problem Chevron down icon Chevron up icon
Unraveling a Mess Chevron down icon Chevron up icon
A Better Foot Forward Chevron down icon Chevron up icon
Other Books You May Enjoy Chevron down icon Chevron up icon

Customer reviews

Top Reviews
Rating distribution
Full star icon Full star icon Full star icon Full star icon Empty star icon 4
(11 Ratings)
5 star 63.6%
4 star 0%
3 star 9.1%
2 star 27.3%
1 star 0%
Filter icon Filter
Top Reviews

Filter reviews by




Pedro Quintero Mar 27, 2018
Full star icon Full star icon Full star icon Full star icon Full star icon 5
This is an excellent book, both as a reference and as an introduction to test-driven development. This book is for intermediate level programmers, it's full of best-practices and is easy to follow, with practical examples and clear narrative. I wish there was a companion site for the code used in the book. I found useful techniques (besides TDD) here that I am using in my projects. Highly recommended.
Amazon Verified review Amazon
Amazon Customer Jul 05, 2018
Full star icon Full star icon Full star icon Full star icon Full star icon 5
I have been struggling for some time as a solo developer to produce quality code on time within the expectation of the stakeholder. I never have enough time to debug and test. I had heard of TDD before this book but thought of it as something to abstract for my to tackle in the heat of the battle. However, last weekend I opened this book that I heard about on the Completed Developer Podcast. I consumed it in about 18 hours. By the end of the book, something that seemed far away was within reach. I had a section of code that I needed to refractor bad. So, using TDD I started developing a microservice to replace the back-end portion. It was slow at first, but once I got into a stride with Moq and XUnit, and with the examples from the book, I was off to the races. I will not say I have implemented TDD perfectly in this case or have great code coverage etc… But I feel a lot more comfortable and confident launching this feature update in a week than I have in any past launches over the last two years. I just know the code works.From a professionalism stand point I feel like I just made a huge leap forward in my code writing it just seems better and makes so much sense. The huge part to the story is that I am a contract consultant. With my current customer I was probably one failed demo away from have a cancelation notice issued. I know now for a fact that the demo will go as planned. There will not be any “oh crap I forgot to fix that”, while showing the features to the customer. The launch will go better, everyone is happy. Thank you both for writing this book in a very understanding and meaningful way. The examples and download code are spot and super easy to walk through.
Amazon Verified review Amazon
Crystal Tenn Mar 01, 2018
Full star icon Full star icon Full star icon Full star icon Full star icon 5
This book is a great read, is feels very practical and easy to understand. I like how the intro breaks down TDD and related terminology into layman terms then digs deeper with samples, tips, and best practices for a realistic enterprise view. There is certainly developer humor in the writing, and it is easy to relate to the authors and many of the feelings good and bad I have had about enterprise code are echoed in the text. I love how the book has broken up different ideas into small digestible sections that make good chronological and logical order. Many texts are chock full of words without much direction, and they found a way to make a practical order so learning is easier.The book covers specific examples using C#, JavaScript (and React), and helps you setup sample code with clear instructions. Also, they talk about un-testable code, which is equally important to be able to recognize. If you know what can't be tested, you know how to write better code that can maximize the amount of tested code which was great to read about! I was also happy to see mocking, design patterns, dependency injection, and APIs covered in the text in addition as it relates to TDD.Overall, I think if you want to learn TDD and have little or a lot of experience, you can still learn a lot from this book. I highly recommended reading it and wish I had a copy of it when I first started development!
Amazon Verified review Amazon
Ward Mar 15, 2018
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Clean, simple, and easy to understand approach to TDD.The authors hit one out of the ballpark with this one. The authors not only know TDD but also understand the problems developers, like myself, face involving TDD. Some of these problems are understanding the concepts, setting up an environment, or even digging into old code. They have covered the material from the viewpoint of standing up a new application all the way to, the dreaded, legacy code - that stuff we seem to get handed and have no idea how to handle. Now we have a strategy!What I like most about this book is the journey the reader is taken on. No assumptions are made, every topic has clear explanations, examples, and when applicable, code samples. What's more, the discussions focus on both C# and JavaScript - two of the largest used languages for both frontend and backend development.In prior years, I've struggled with knowing how to implement TDD into my development team. The one piece I was missing, which this book highlights perfectly, is the mindset on testing first. Thinking about tests first, instead of writing code results in better code. By better code, of course, I mean fewer bugs and increasingly faster development time.
Amazon Verified review Amazon
Jay V May 16, 2018
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Overall, this is a great introduction to Test Driven Development in .NET, and in general. In the process, it's also a pretty good introduction to building an ASP.NET Core application from scratch.I really appreciated how the authors were able to provide examples of many of the actual problems I've seen when trying to apply TDD principles, and then provide practical solutions (sometimes more than one). I also liked seeing the different approaches to TDD in various application layers, e.g. using Mocha and Chai in a React front-end. I'm not sure I'd 100% agree with their choices of test frameworks, but the examples provided were easy enough to follow along and apply in any environment.
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact customercare@packt.com with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at customercare@packt.com using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on customercare@packt.com with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on customercare@packt.com within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on customercare@packt.com who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on customercare@packt.com within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela