Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
Arrow up icon
GO TO TOP
Domain-Driven Design with Golang

You're reading from   Domain-Driven Design with Golang Use Golang to create simple, maintainable systems to solve complex business problems

Arrow left icon
Product type Paperback
Published in Dec 2022
Publisher Packt
ISBN-13 9781804613450
Length 204 pages
Edition 1st Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
Matthew Boyle Matthew Boyle
Author Profile Icon Matthew Boyle
Matthew Boyle
Arrow right icon
View More author details
Toc

Table of Contents (13) Chapters Close

Preface 1. Part 1: Introduction to Domain-Driven Design
2. Chapter 1: A Brief History of Domain-Driven Design FREE CHAPTER 3. Chapter 2: Understanding Domains, Ubiquitous Language, and Bounded Contexts 4. Chapter 3: Entities, Value Objects, and Aggregates 5. Chapter 4: Exploring Factories, Repositories, and Services 6. Part 2: Real -World Domain-Driven Design with Golang
7. Chapter 5: Applying Domain-Driven Design to a Monolithic Application 8. Chapter 6: Building a Microservice Using DDD 9. Chapter 7: DDD for Distributed Systems 10. Chapter 8: TDD, BDD, and DDD 11. Index 12. Other Books You May Enjoy

BDD

BDD is an extension of TDD that aims to enable deeper collaboration between engineers, domain experts, and quality assurance engineers (if your company employs them). A diagram of how this works with TDD is shown here.

Figure 8.6 – BDD as an extension of TDD

Figure 8.6 – BDD as an extension of TDD

The goal of BDD is to provide a higher level of abstraction from code through a domain-specific language (often referred to as a DSL) that can become executable tests. Two popular frameworks for writing BDD tests is the use of Gherkin (https://cucumber.io/docs/gherkin/reference/) and Cucumber (https://cucumber.io)

Gherkin defines a set of keywords and a language specification. Cucumber reads this text and validates that the software works as expected. For example, the following is a valid Cucumber test:

Feature: checkout Integration
Scenario: Successfully Capture a payment
Given I am a customer
When I purchase a cookie for 50 cents.
Then my card should be charged 50 cents and an e-mail receipt is sent.

Some teams work with their domain experts to ensure their acceptance criteria in their ticketing system are in this format. If it is, this criterion can simply become the test. This aligns nicely with DDD.

Now that we have a high-level understanding of BDD, let’s take a look at implementing a test in Go. We are going to use the go-bdd framework, which you can find at https://github.com/go-bdd/gobdd.

Firstly, let’s install go-bdd in our project:

go get github.com/go-bdd/gobdd

Now, create a features folder:

Figure 8.7 – Our features folder after creation

Figure 8.7 – Our features folder after creation

Inside the features folder, let’s add a file called add.feature with this inside it:

Feature: Adding numbers
  Scenario: add two numbers together
    When I add 3 and 6
    Then the result should equal 9

Next, let’s add an add_test.go file and the following:

package chapter8
import (
   "testing"
   "github.com/go-bdd/gobdd"
)
func add(t gobdd.StepTest, ctx gobdd.Context, first, second int) {
   res := first + second
   ctx.Set("result", res)
}
func check(t gobdd.StepTest, ctx gobdd.Context, sum int) {
   received, err := ctx.GetInt("result")
   if err != nil {
      t.Fatal(err)
      return
   }
   if sum != received {
      t.Fatalf("expected %d but got %d", sum, received)
   }
}
func TestScenarios(t *testing.T) {
   suite := gobdd.NewSuite(t)
   suite.AddStep(`I add (\d+) and (\d+)`, add)
   suite.AddStep(`the result should equal (\d+)`, check)
   suite.Run()
}

In the preceding code, we add a bdd step function called add. This function name is important; the framework knows that when I add 3 and 6 gets mapped to this function. If you change the name of this function to “sum”, you’d need to update the feature file to say, when I sum 3 and 6 together. We then perform our logic and store it in the context so that we can recall it later.

We then define a check function that is our actual test; it validates our assertions. Finally, we set up a test suite to run our code.

If you run the preceding test, it should pass.

This might be your first time seeing a BDD-style test, but I bet it’s not your first time seeing a unit test. Why is that?

As you can see, although BDD tests are closer to natural language, it pushes a lot of the complexity down into the tests. The preceding example we used is trivial, but if you want to express complex scenarios (such as the cookie example we used previously) there is a lot of scaffolding the developer needs to implement to make the tests work correctly. This can be worthwhile if you have lots of access to your domain experts and you are truly going to work side by side. However, if they are absent or not invested in the process, unit tests are much faster and more engaging for engineering teams to work with. Much like DDD, BDD is a multidisciplinary team investment, and it is worth ensuring you have buy-in from all stakeholders before investing too much time in it.

lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime