SlideShare a Scribd company logo
1 of 61
TDD is not about
testing
Bad name for good technique ...
GPad
Born to be a developer with an interest in distributed system.
I have developed with many languages like C++, C#, js and ruby. I had fallen in
love with functional programming, especially with elixir, erlang.
● Twitter: https://twitter.com/gpad619
● Github: https://github.com/gpad/
● Medium: https://medium.com/@gpad
CTO & founder of coders51
Schedule
What is TDD?
Why TDD?
TDD is not (only) Unit Testing
TDD in OOP
Examples
What is TDD - History
Wikipedia - TDD
Wikipedia - Extreme Programming
Quora - Why does Kent Beck rediscover TDD
http://wiki.c2.com/?TestingFramework
Wikipedia - C2 System
What is TDD - History
The C3 project started in 1993 [...]. Smalltalk development was initiated in 1994. [...] In
1996 Kent Beck was hired [...]; at this point the system had not printed a single
paycheck.
In March 1996 the development team estimated the system would be ready to go into
production around one year later.
In 1997 the development team adopted a way of working which is now formalized as
Extreme Programming.
The one-year delivery target was nearly achieved, with actual delivery being a couple of
months late;
What is TDD - History
It was developed by Grady Booch, Ivar Jacobson
and James Rumbaugh at Rational Software in 1994–
1995, with further development led by them
through 1996.
In 1997 UML was adopted as a standard by the
Object Management Group (OMG) [...].
In 2005 UML was also published by the International Organization for
Standardization (ISO) as an approved ISO standard. Since then the standard
has been periodically revised to cover the latest revision of UML.
What is TDD - History
What is TDD - History
From Wikipedia:
Test-driven development (TDD) is a software development process that relies on the
repetition of a very short development cycle: requirements are turned into very specific
test cases, then the software is improved to pass the new tests, only.
This is opposed to software development that allows software to be added that is not
proven to meet requirements.
American software engineer Kent Beck, who is credited with having developed or
"rediscovered" the technique, stated in 2003 that TDD encourages simple designs and
inspires confidence.
What is TDD
What is TDD
1. Add a test
2. Run all tests and see if the new test
fails (RED)
3. Write the code (Only to make the
test pass!!!)
4. Run tests
5. Refactor code
6. Repeat
Why TDD
Why TDD
Less bugs
I like it …
I feel more comfortable …
…
Helps to create a “GOOD” design
Why TDD
TDD changes the point of view.
Forces the developer to think about the “behaviour” of the code.
Talks to the developer showing what are the “difficult points” of the code.
If the tests talk, we should listen them … (often we ignore them).
Listen the test
TEST(MailComposerTest, test1)
{
User gino{"gino", "gino@gino.it", true};
User pino{"pino", "pino@pino.it", false};
auto userRepository = UserRepository::create();
userRepository->CreateUser(gino);
userRepository->CreateUser(pino);
MailComposer composer;
composer.SendEmail("gino@gino.it", "body one");
composer.SendEmail("pino@pino.it", "body two");
auto emailsSent = ExternalLibrary::TestEmailServer::GetEmailsSent();
ASSERT_EQ(emailsSent.size(), 1);
ExternalLibrary::Email expected{"gino@gino.it", GlobalSettings::GetFromAddress(), "body one"};
ASSERT_EQ(*emailsSent.begin(), expected);
}
Listen the test
class MailComposer
{
public:
void SendEmail(std::string email, std::string body)
{
using namespace ExternalLibrary;
auto userRepository = UserRepository::create();
auto user = userRepository->GetUserByEmail(email);
if (!user.acceptEmail())
return;
EmailServer::GetInstance()->SendEmail(Email{
GlobalSettings::GetFromAddress(),
user.email(),
body});
}
};
Listen the test
It isn’t a tool problem.
It’s a design problem …
What is telling (screaming) the test?
Listen the test
TEST(MailComposerTest, test1)
{
User gino{"gino", "gino@gino.it", true};
User pino{"pino", "pino@pino.it", false};
auto userRepository = UserRepository::create();
userRepository->CreateUser(gino);
userRepository->CreateUser(pino);
MailComposer composer;
composer.SendEmail("gino@gino.it", "body one");
composer.SendEmail("pino@pino.it", "body two");
auto emailsSent = ExternalLibrary::TestEmailServer::GetEmailsSent();
ASSERT_EQ(emailsSent.size(), 1);
ExternalLibrary::Email expected{"gino@gino.it", GlobalSettings::GetFromAddress(), "body one"};
ASSERT_EQ(*emailsSent.begin(), expected);
}
The name doesn’t mean anything
We are changing global value
Singleton ?!?
Listen the test
TEST(MailComposerTest, SendEmailOnlyToUserThatAcceptEmail)
{
User gino{"gino", "gino@gino.it", true};
User pino{"pino", "pino@pino.it", false};
auto userRepository = UserRepository::create();
userRepository->CreateUser(gino);
userRepository->CreateUser(pino);
MailComposer composer(
userRepository,
ExternalLibrary::EmailServer::GetInstance());
composer.SendEmail("gino@gino.it", "body one");
composer.SendEmail("pino@pino.it", "body two");
auto emailsSent = ExternalLibrary::TestEmailServer::GetEmailsSent();
ASSERT_EQ(emailsSent.size(), 1);
ExternalLibrary::Email expected{"gino@gino.it", GlobalSettings::GetFromAddress(), "body one"};
ASSERT_EQ(*emailsSent.begin(), expected);
}
Change name!!!
Passing repository as parameter ...
Passing Singleton as parameter
Can we do better?!?
TDD doesn’t mean only Unit Testing ...
Type of tests
End to End tests - Tests that work on the entire stack.
Integration Test - Tests that work on some parts of the application.
Unit Test - Tests that work on a single “module/function”.
Why is it so important to know which type of test we are writing?
Because we get different feedbacks from different types of test.
Type of tests
Cycle of TDD ...
1. Add a test
2. Run all tests and see if the new
test fails (RED)
3. Write the code
4. Run tests
5. Refactor code
6. Repeat
Cycle of TDD ...
End To End Test or Acceptance Test
This type of test exercises the entire stack of the application.
It remains RED until the feature is completed.
Don’t write too much E2E.
They are slow and fragile.
Where is the design?
How application is done (or should be)
How application is done (or should be)
Try to create a E2E test that interacts
with system from the external.
If it’s “impossible” try to move a little
inside skipping the adapter.
Outside-In VS Inside-Out
Outside-In
We start writing an End to End Test that explains the feature that we want to
create.
We add some unit tests to shape the behaviour of the object that we want to
create.
We add some integration tests to verify that some parts works well together.
Inside-Out
We start writing some units test to shape the behaviour of the objects that we
want to create.
We add some integration tests to verify that the parts works well together.
We add some End to End Tests that explain the feature that we want to create.
My 2 cents
I prefer to use Outside-In when I have to create a new feature.
Outside-In requires more experienced developers/teams.
I use Inside-Out when I want to introduce the TDD in a new team.
I use Inside-Out when I have to add a feature and I know which objects I have
to change.
Mock
When to use Mock?
When we want to isolate one part from another.
Classic example HTTP connections.
We have to make some HTTP calls and manipulate the results in some ways.
How can we do it?
When to use Mock?
TEST(TwitterClientTest, RetriveBioFromUser)
{
std::string clientId = "cleintId";
std::string clientSecret = "clientSecret";
NiceMock<MockHttpClient> mockHttpClient;
EXPECT_CALL(mockHttpClient, Get("https://twitter.com/gpad619"))
.WillOnce(Return("gpad_bio"));
TwitterClient twitter(clientId, clientSecret, &mockHttpClient);
auto bio = twitter.GetBioOf("gpad619");
EXPECT_EQ(bio, "gpad_bio");
}
When to use Mock?
We are at the boundaries of our
system and we can use the mock to
shape the behavior between the
CORE and the adapter that talks with
the external system.
It’s the CORE that choose the shape
of the data and how the functions
should be done.
When to use Mock?
TEST(AggregationTest, SaveTheSumWhenThresholdIsReached)
{
NiceMock<MockPointRepository> mockPointRepository;
EXPECT_CALL(mockPointRepository, Store(4));
Aggregation aggregation(4, &mockPointRepository);
aggregation.Add(2);
aggregation.Add(2);
}
When to use Mock? - Time
TEST(AggregationTest, SaveTheEventWhenThresholdIsReached)
{
auto now = std::chrono::system_clock::now();
NiceMock<MockPointRepository> mockPointRepository;
EXPECT_CALL(mockPointRepository, StoreEvent("Threshold Reached", now));
Aggregation aggregation(4, &mockPointRepository);
aggregation.Add(2);
aggregation.Add(2);
}
When to use Mock? - Time
When to use Mock? - Time
class Aggregation
{
int _sum;
int _threshold;
PointRepository *_pointRepository;
public:
void Add(int value)
{
_sum += value;
if (_sum >= _threshold)
{
_pointRepository->Store(_sum);
_pointRepository->StoreEvent("Threshold Reached", std::chrono::system_clock::now());
}
}
};
This is a dependency!!!
When to use Mock? - Time
TEST(AggregationTest, SaveTheEventWhenThresholdIsReached)
{
auto now = std::chrono::system_clock::now();
NiceMock<MockPointRepository> mockPointRepository;
EXPECT_CALL(mockPointRepository, StoreEvent("Threshold Reached", now));
NiceMock<MockClock> mockClock;
ON_CALL(mockClock, Now()).WillByDefault(Return(now));
Aggregation aggregation(4, &mockPointRepository, &mockClock);
aggregation.Add(2);
aggregation.Add(2);
}
When to use Mock? - Time
class Aggregation
{
...;
public:
Aggregation(int threshold, PointRepository *pointReposiotry, Clock *clock) ...
void Add(int value)
{
_sum += value;
if (_sum >= _threshold)
{
_pointRepository->Store(_sum);
_pointRepository->StoreEvent("Threshold Reached", _clock->Now());
}
}
};
When to use Mock? - Time
How to manage a periodic task?
Divide et impera.
When to use Mock? - Time
TEST(Scheduler, ExecuteTaskAfterSomeAmountOfTime)
{
Scheduler scheduler;
bool executed = false;
scheduler.ExecuteAfter(
std::chrono::milliseconds(500),
[&]() { executed = true; });
EXPECT_THAT(executed, WillBe(true, std::chrono::milliseconds(1000)));
}
When to use Mock? - Time
TEST(Scheduler, DontExecuteTaskImmediatly)
{
Scheduler scheduler;
bool executed = false;
scheduler.ExecuteAfter(
std::chrono::milliseconds(500),
[&]() { executed = true; });
EXPECT_FALSE(executed);
}
WHERE to use Mock?
Use the mock at the external of
CORE/Domain (adapter).
Isolate the CORE from the infrastructure
not because we want to switch from PG
to Mongo but because that libraries are
not under our control.
When to use Mock? - Interaction between objects
TEST(CartTest, RetrieveDiscoutForUserWhenAddItem)
{
User user("gino", "g@g.it", true);
NiceMock<MockTrackingSystem> mockTrackingSystem;
NiceMock<MockDiscountEngine> mockDiscountEngine;
EXPECT_CALL(mockDiscountEngine, GetDiscountFor(user))
.WillRepeatedly(Return(0.1));
Cart cart(user, &mockDiscountEngine, &mockTrackingSystem);
cart.AddItem(Product(ProductId::New(), "Product", Money(10, "EUR")));
EXPECT_EQ(cart.GetTotal(), Money(9, "EUR"));
}
When to use Mock? - Interaction between objects
TEST(CartTest, CallTrackingSystemWhenRemoveItemFromCart)
{
User user("gino", "g@g.it", true);
Product product(ProductId::New(), "Product", Money(10, "EUR"));
NiceMock<MockTrackingSystem> mockTrackingSystem;
NiceMock<MockDiscountEngine> mockDiscountEngine;
EXPECT_CALL(mockTrackingSystem, ProductRemoved(product));
Cart cart(user, &mockDiscountEngine, &mockTrackingSystem);
cart.AddItem(product);
cart.RemoveItem(product);
}
WHERE to use Mock?
We can use the mock when we want to
define how the object talk to each
other.
We can define the protocol that the
object should use to talk to each other.
When not to use Mock?
Don’t use mock on Object that don’t own.
TEST(MailComposerTest, TestMailComposerMock)
{
User gino{"gino", "gino@gino.it", true};
User pino{"pino", "pino@pino.it", false};
auto userRepository = UserRepository::create();
userRepository->CreateUser(gino);
userRepository->CreateUser(pino);
NiceMock<MockExternalEmailServer> mockExternalEmailServer;
MailComposer composer(userRepository, &mockExternalEmailServer);
...
}
When not to use Mock?
Don’t mock value objects!!!
TEST(MailComposerTest, TestMailComposerMockUser)
{
NiceMock<MockUser> gino();
NiceMock<MockUser> pino();
EXPECT_CALL(gino, acceptEmail()).WillRepeatedly(Return(true));
EXPECT_CALL(pino, acceptEmail()).WillRepeatedly(Return(true));
auto userRepository = UserRepository::create();
MailComposer composer(userRepository, ExternalLibrary::EmailServer::GetInstance());
composer.SendEmail(gino, "body one");
composer.SendEmail(pino, "body two");
}
TDD - Mix Everything together
What is the first test to do?
We could start from outside with an E2E test to enter inside our application.
Or we could start inside our application adding some unit tests to some
objects.
Create at least one E2E for every User Story.
Don’t create too much E2E they are slow and fragile.
TDD - Mix Everything together
TEST_F(AsLoggedUser, IWantSeeMyCurrentCart)
{
auto cart = CreateCartFor(_currentUser);
auto total = GetMainWindow()
->GetCartWindowFor(_currentUser)
->GetTotal();
EXPECT_EQ(total, cart.GetTotal());
}
TDD - Mix Everything together
TEST_F(AsLoggedUser, IWantPayMyCurrentCart)
{
auto cart = CreateCartFor(_currentUser);
auto paymentInfo = CreatePaymentInfoFor(_currentUser);
auto paymentResult = GetMainWindow()
->GetPaymentWindowFor(_currentUser)
->Pay();
EXPECT_EQ(paymentResult, PaymentResult::Successful);
}
TDD - Mix Everything together
The E2E remains RED until all the cycle is completed.
After that we have written the E2E we go inside the CORE and start to create
some unit tests.
TDD - Mix Everything together
TEST(CartTest, CalculateCartTotalWhenAddItem)
{
User user("gino", "g@g.it", true);
NiceMock<MockTrackingSystem> mockTrackingSystem;
NiceMock<MockDiscountEngine> mockDiscountEngine;
Cart cart(user, &mockDiscountEngine, &mockTrackingSystem);
cart.AddItem(Product(ProductId::New(), "Product1", Money(5, "EUR")));
cart.AddItem(Product(ProductId::New(), "Product2", Money(4, "EUR")));
EXPECT_EQ(cart.GetTotal(), Money(9, "EUR"));
}
TDD - Mix Everything together
After we have written the unit tests for the CORE we could move to the
boundaries where we should write tests for the adapter parts.
The test for storage part should be written using the DB. IMHO they are more
integration than unit.
TDD - Mix Everything together
TEST_F(SqlCartRepositoryTest, ReadSavedCartById)
{
Cart cart = BuildCartWithSomeItemsFor(_currentUser);
_cartRepository.Save(cart);
auto cartFromDb = _cartRepository.GetById(cart.GetId());
EXPECT_THAT(cart, IsEquivalent(cartFromDb));
}
TDD - Mix Everything together
Writing these tests BEFORE the implementation we are doing DESIGN.
We are shaping the production code.
The code became more “composable”.
It’s more clear where are side effects (I/O, Time).
It’s more clear what are the different parts of our applications.
Recap
TDD is not a Silver Bullet.
TDD doesn’t give us a “good” design if we are not able to do it.
TDD can help us to find some issues in our design.
Listen the test, often they are screaming in pain ...
Reference
Modern C++ Programming with Test-Driven Development
GOOS
Clean Architecture
Clean Code
WELC
The Rspec Book
End - Thanks !!!

More Related Content

What's hot

Clean Code I - Design Patterns and Best Practices at SoCal Code Camp San Dieg...
Clean Code I - Design Patterns and Best Practices at SoCal Code Camp San Dieg...Clean Code I - Design Patterns and Best Practices at SoCal Code Camp San Dieg...
Clean Code I - Design Patterns and Best Practices at SoCal Code Camp San Dieg...Theo Jungeblut
 
Clean Code II - Dependency Injection at SoCal Code Camp San Diego (07/27/2013)
Clean Code II - Dependency Injection at SoCal Code Camp San Diego (07/27/2013)Clean Code II - Dependency Injection at SoCal Code Camp San Diego (07/27/2013)
Clean Code II - Dependency Injection at SoCal Code Camp San Diego (07/27/2013)Theo Jungeblut
 
How we tested our code "Google way"
How we tested our code "Google way"How we tested our code "Google way"
How we tested our code "Google way"Oleksiy Rezchykov
 
Clean Code at Silicon Valley Code Camp 2011 (02/17/2012)
Clean Code at Silicon Valley Code Camp 2011 (02/17/2012)Clean Code at Silicon Valley Code Camp 2011 (02/17/2012)
Clean Code at Silicon Valley Code Camp 2011 (02/17/2012)Theo Jungeblut
 
Test driven development vs Behavior driven development
Test driven development vs Behavior driven developmentTest driven development vs Behavior driven development
Test driven development vs Behavior driven developmentGallop Solutions
 
Tdd practices
Tdd practicesTdd practices
Tdd practicesaxykim00
 
TDD - Test Driven Development
TDD - Test Driven DevelopmentTDD - Test Driven Development
TDD - Test Driven DevelopmentLim Chanmann
 
Measuring Code Quality in WTF/min.
Measuring Code Quality in WTF/min. Measuring Code Quality in WTF/min.
Measuring Code Quality in WTF/min. David Gómez García
 
DevSecCon SG 2018 Fabian Presentation Slides
DevSecCon SG 2018 Fabian Presentation SlidesDevSecCon SG 2018 Fabian Presentation Slides
DevSecCon SG 2018 Fabian Presentation SlidesFab L
 
Cut your Dependencies with - Dependency Injection for South Bay.NET User Grou...
Cut your Dependencies with - Dependency Injection for South Bay.NET User Grou...Cut your Dependencies with - Dependency Injection for South Bay.NET User Grou...
Cut your Dependencies with - Dependency Injection for South Bay.NET User Grou...Theo Jungeblut
 
Clean Code Part i - Design Patterns and Best Practices -
Clean Code Part i - Design Patterns and Best Practices -Clean Code Part i - Design Patterns and Best Practices -
Clean Code Part i - Design Patterns and Best Practices -Theo Jungeblut
 
TDD and Simple Design Workshop - Session 1 - March 2019
TDD and Simple Design Workshop - Session 1 - March 2019TDD and Simple Design Workshop - Session 1 - March 2019
TDD and Simple Design Workshop - Session 1 - March 2019Paulo Clavijo
 
Test Driven Development (TDD) Preso 360|Flex 2010
Test Driven Development (TDD) Preso 360|Flex 2010Test Driven Development (TDD) Preso 360|Flex 2010
Test Driven Development (TDD) Preso 360|Flex 2010guest5639fa9
 
cf.Objective() 2017 - Design patterns - Brad Wood
cf.Objective() 2017 - Design patterns - Brad Woodcf.Objective() 2017 - Design patterns - Brad Wood
cf.Objective() 2017 - Design patterns - Brad WoodOrtus Solutions, Corp
 

What's hot (20)

Clean Code I - Design Patterns and Best Practices at SoCal Code Camp San Dieg...
Clean Code I - Design Patterns and Best Practices at SoCal Code Camp San Dieg...Clean Code I - Design Patterns and Best Practices at SoCal Code Camp San Dieg...
Clean Code I - Design Patterns and Best Practices at SoCal Code Camp San Dieg...
 
Clean Code II - Dependency Injection at SoCal Code Camp San Diego (07/27/2013)
Clean Code II - Dependency Injection at SoCal Code Camp San Diego (07/27/2013)Clean Code II - Dependency Injection at SoCal Code Camp San Diego (07/27/2013)
Clean Code II - Dependency Injection at SoCal Code Camp San Diego (07/27/2013)
 
Tdd
TddTdd
Tdd
 
Tdd
TddTdd
Tdd
 
Test driven development(tdd)
Test driven development(tdd)Test driven development(tdd)
Test driven development(tdd)
 
How we tested our code "Google way"
How we tested our code "Google way"How we tested our code "Google way"
How we tested our code "Google way"
 
Clean Code at Silicon Valley Code Camp 2011 (02/17/2012)
Clean Code at Silicon Valley Code Camp 2011 (02/17/2012)Clean Code at Silicon Valley Code Camp 2011 (02/17/2012)
Clean Code at Silicon Valley Code Camp 2011 (02/17/2012)
 
Test driven development vs Behavior driven development
Test driven development vs Behavior driven developmentTest driven development vs Behavior driven development
Test driven development vs Behavior driven development
 
Tdd practices
Tdd practicesTdd practices
Tdd practices
 
TDD - Test Driven Development
TDD - Test Driven DevelopmentTDD - Test Driven Development
TDD - Test Driven Development
 
Measuring Code Quality in WTF/min.
Measuring Code Quality in WTF/min. Measuring Code Quality in WTF/min.
Measuring Code Quality in WTF/min.
 
Tdd com Java
Tdd com JavaTdd com Java
Tdd com Java
 
DevSecCon SG 2018 Fabian Presentation Slides
DevSecCon SG 2018 Fabian Presentation SlidesDevSecCon SG 2018 Fabian Presentation Slides
DevSecCon SG 2018 Fabian Presentation Slides
 
Cut your Dependencies with - Dependency Injection for South Bay.NET User Grou...
Cut your Dependencies with - Dependency Injection for South Bay.NET User Grou...Cut your Dependencies with - Dependency Injection for South Bay.NET User Grou...
Cut your Dependencies with - Dependency Injection for South Bay.NET User Grou...
 
TDD = bra design?
TDD = bra design?TDD = bra design?
TDD = bra design?
 
Clean Code Part i - Design Patterns and Best Practices -
Clean Code Part i - Design Patterns and Best Practices -Clean Code Part i - Design Patterns and Best Practices -
Clean Code Part i - Design Patterns and Best Practices -
 
TDD and Simple Design Workshop - Session 1 - March 2019
TDD and Simple Design Workshop - Session 1 - March 2019TDD and Simple Design Workshop - Session 1 - March 2019
TDD and Simple Design Workshop - Session 1 - March 2019
 
Test Driven Development (TDD) Preso 360|Flex 2010
Test Driven Development (TDD) Preso 360|Flex 2010Test Driven Development (TDD) Preso 360|Flex 2010
Test Driven Development (TDD) Preso 360|Flex 2010
 
cf.Objective() 2017 - Design patterns - Brad Wood
cf.Objective() 2017 - Design patterns - Brad Woodcf.Objective() 2017 - Design patterns - Brad Wood
cf.Objective() 2017 - Design patterns - Brad Wood
 
Test drive on driven development process
Test drive on driven development processTest drive on driven development process
Test drive on driven development process
 

Similar to TDD is not only unit testing

Tdd is not about testing (OOP)
Tdd is not about testing (OOP)Tdd is not about testing (OOP)
Tdd is not about testing (OOP)Gianluca Padovani
 
Test-Driven Development In Action
Test-Driven Development In ActionTest-Driven Development In Action
Test-Driven Development In ActionJon Kruger
 
Test driven development in .Net - 2010 + Eclipse
Test driven development in .Net - 2010 + EclipseTest driven development in .Net - 2010 + Eclipse
Test driven development in .Net - 2010 + EclipseUTC Fire & Security
 
Art of unit testing: how to do it right
Art of unit testing: how to do it rightArt of unit testing: how to do it right
Art of unit testing: how to do it rightDmytro Patserkovskyi
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Developmentbhochhi
 
Test Driven Development (TDD) with FlexUnit 4 - 360|Flex San Jose preso
Test Driven Development (TDD) with FlexUnit 4 - 360|Flex San Jose presoTest Driven Development (TDD) with FlexUnit 4 - 360|Flex San Jose preso
Test Driven Development (TDD) with FlexUnit 4 - 360|Flex San Jose presoElad Elrom
 
TDD reloaded - JUGTAA 24 Ottobre 2012
TDD reloaded - JUGTAA 24 Ottobre 2012TDD reloaded - JUGTAA 24 Ottobre 2012
TDD reloaded - JUGTAA 24 Ottobre 2012Pietro Di Bello
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Developmentguestc8093a6
 
Test driven development
Test driven developmentTest driven development
Test driven developmentnamkha87
 
Test Driven iOS Development (TDD)
Test Driven iOS Development (TDD)Test Driven iOS Development (TDD)
Test Driven iOS Development (TDD)Babul Mirdha
 
Test driven development_continuous_integration
Test driven development_continuous_integrationTest driven development_continuous_integration
Test driven development_continuous_integrationhaochenglee
 
Writing Tests with the Unity Test Framework
Writing Tests with the Unity Test FrameworkWriting Tests with the Unity Test Framework
Writing Tests with the Unity Test FrameworkPeter Kofler
 
TDD with Visual Studio 2010
TDD with Visual Studio 2010TDD with Visual Studio 2010
TDD with Visual Studio 2010Stefano Paluello
 

Similar to TDD is not only unit testing (20)

Tdd is not about testing (OOP)
Tdd is not about testing (OOP)Tdd is not about testing (OOP)
Tdd is not about testing (OOP)
 
Tdd is not about testing
Tdd is not about testingTdd is not about testing
Tdd is not about testing
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Development
 
Test-Driven Development In Action
Test-Driven Development In ActionTest-Driven Development In Action
Test-Driven Development In Action
 
Test driven development in .Net - 2010 + Eclipse
Test driven development in .Net - 2010 + EclipseTest driven development in .Net - 2010 + Eclipse
Test driven development in .Net - 2010 + Eclipse
 
Art of unit testing: how to do it right
Art of unit testing: how to do it rightArt of unit testing: how to do it right
Art of unit testing: how to do it right
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Development
 
Test Driven Development (TDD) with FlexUnit 4 - 360|Flex San Jose preso
Test Driven Development (TDD) with FlexUnit 4 - 360|Flex San Jose presoTest Driven Development (TDD) with FlexUnit 4 - 360|Flex San Jose preso
Test Driven Development (TDD) with FlexUnit 4 - 360|Flex San Jose preso
 
Python and test
Python and testPython and test
Python and test
 
Ian Cooper webinar for DDD Iran: Kent beck style tdd seven years after
Ian Cooper webinar for DDD Iran: Kent beck style tdd   seven years afterIan Cooper webinar for DDD Iran: Kent beck style tdd   seven years after
Ian Cooper webinar for DDD Iran: Kent beck style tdd seven years after
 
TDD reloaded - JUGTAA 24 Ottobre 2012
TDD reloaded - JUGTAA 24 Ottobre 2012TDD reloaded - JUGTAA 24 Ottobre 2012
TDD reloaded - JUGTAA 24 Ottobre 2012
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Development
 
TDD Workshop UTN 2012
TDD Workshop UTN 2012TDD Workshop UTN 2012
TDD Workshop UTN 2012
 
TDD Best Practices
TDD Best PracticesTDD Best Practices
TDD Best Practices
 
Test driven development
Test driven developmentTest driven development
Test driven development
 
Test Driven iOS Development (TDD)
Test Driven iOS Development (TDD)Test Driven iOS Development (TDD)
Test Driven iOS Development (TDD)
 
Test driven development_continuous_integration
Test driven development_continuous_integrationTest driven development_continuous_integration
Test driven development_continuous_integration
 
Writing Tests with the Unity Test Framework
Writing Tests with the Unity Test FrameworkWriting Tests with the Unity Test Framework
Writing Tests with the Unity Test Framework
 
TDD with Visual Studio 2010
TDD with Visual Studio 2010TDD with Visual Studio 2010
TDD with Visual Studio 2010
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Development
 

More from Gianluca Padovani

A Gentle introduction to microservices
A Gentle introduction to microservicesA Gentle introduction to microservices
A Gentle introduction to microservicesGianluca Padovani
 
Beam me up, scotty (PUG Roma)
Beam me up, scotty (PUG Roma)Beam me up, scotty (PUG Roma)
Beam me up, scotty (PUG Roma)Gianluca Padovani
 
DDD loves Actor Model and Actor Model loves Elixir
DDD loves Actor Model and Actor Model loves ElixirDDD loves Actor Model and Actor Model loves Elixir
DDD loves Actor Model and Actor Model loves ElixirGianluca Padovani
 
From a web application to a distributed system
From a web application to a distributed systemFrom a web application to a distributed system
From a web application to a distributed systemGianluca Padovani
 
System integration through queues
System integration through queuesSystem integration through queues
System integration through queuesGianluca Padovani
 
La mia prima lezione di pozioni
La mia prima lezione di pozioniLa mia prima lezione di pozioni
La mia prima lezione di pozioniGianluca Padovani
 
Keynote meetup Elixir/Erlang 17 ottobre 2015
Keynote meetup Elixir/Erlang 17 ottobre 2015Keynote meetup Elixir/Erlang 17 ottobre 2015
Keynote meetup Elixir/Erlang 17 ottobre 2015Gianluca Padovani
 
C++ Actor Model - You’ve Got Mail ...
C++ Actor Model - You’ve Got Mail ...C++ Actor Model - You’ve Got Mail ...
C++ Actor Model - You’ve Got Mail ...Gianluca Padovani
 

More from Gianluca Padovani (14)

A Gentle introduction to microservices
A Gentle introduction to microservicesA Gentle introduction to microservices
A Gentle introduction to microservices
 
Beam me up, scotty (PUG Roma)
Beam me up, scotty (PUG Roma)Beam me up, scotty (PUG Roma)
Beam me up, scotty (PUG Roma)
 
DDD loves Actor Model and Actor Model loves Elixir
DDD loves Actor Model and Actor Model loves ElixirDDD loves Actor Model and Actor Model loves Elixir
DDD loves Actor Model and Actor Model loves Elixir
 
From a web application to a distributed system
From a web application to a distributed systemFrom a web application to a distributed system
From a web application to a distributed system
 
Beam way of life
Beam way of lifeBeam way of life
Beam way of life
 
Cook your KV
Cook your KVCook your KV
Cook your KV
 
System integration through queues
System integration through queuesSystem integration through queues
System integration through queues
 
Beam me up, Scotty
Beam me up, ScottyBeam me up, Scotty
Beam me up, Scotty
 
Docker e git lab
Docker e git labDocker e git lab
Docker e git lab
 
La mia prima lezione di pozioni
La mia prima lezione di pozioniLa mia prima lezione di pozioni
La mia prima lezione di pozioni
 
Keynote meetup Elixir/Erlang 17 ottobre 2015
Keynote meetup Elixir/Erlang 17 ottobre 2015Keynote meetup Elixir/Erlang 17 ottobre 2015
Keynote meetup Elixir/Erlang 17 ottobre 2015
 
C++ Actor Model - You’ve Got Mail ...
C++ Actor Model - You’ve Got Mail ...C++ Actor Model - You’ve Got Mail ...
C++ Actor Model - You’ve Got Mail ...
 
Ferrara Linux Day 2011
Ferrara Linux Day 2011Ferrara Linux Day 2011
Ferrara Linux Day 2011
 
OOP vs COP
OOP vs COPOOP vs COP
OOP vs COP
 

Recently uploaded

New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesZilliz
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 

Recently uploaded (20)

DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector Databases
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 

TDD is not only unit testing

  • 1. TDD is not about testing Bad name for good technique ...
  • 2. GPad Born to be a developer with an interest in distributed system. I have developed with many languages like C++, C#, js and ruby. I had fallen in love with functional programming, especially with elixir, erlang. ● Twitter: https://twitter.com/gpad619 ● Github: https://github.com/gpad/ ● Medium: https://medium.com/@gpad CTO & founder of coders51
  • 3. Schedule What is TDD? Why TDD? TDD is not (only) Unit Testing TDD in OOP Examples
  • 4. What is TDD - History Wikipedia - TDD Wikipedia - Extreme Programming Quora - Why does Kent Beck rediscover TDD http://wiki.c2.com/?TestingFramework Wikipedia - C2 System
  • 5. What is TDD - History The C3 project started in 1993 [...]. Smalltalk development was initiated in 1994. [...] In 1996 Kent Beck was hired [...]; at this point the system had not printed a single paycheck. In March 1996 the development team estimated the system would be ready to go into production around one year later. In 1997 the development team adopted a way of working which is now formalized as Extreme Programming. The one-year delivery target was nearly achieved, with actual delivery being a couple of months late;
  • 6. What is TDD - History It was developed by Grady Booch, Ivar Jacobson and James Rumbaugh at Rational Software in 1994– 1995, with further development led by them through 1996. In 1997 UML was adopted as a standard by the Object Management Group (OMG) [...]. In 2005 UML was also published by the International Organization for Standardization (ISO) as an approved ISO standard. Since then the standard has been periodically revised to cover the latest revision of UML.
  • 7. What is TDD - History
  • 8. What is TDD - History From Wikipedia: Test-driven development (TDD) is a software development process that relies on the repetition of a very short development cycle: requirements are turned into very specific test cases, then the software is improved to pass the new tests, only. This is opposed to software development that allows software to be added that is not proven to meet requirements. American software engineer Kent Beck, who is credited with having developed or "rediscovered" the technique, stated in 2003 that TDD encourages simple designs and inspires confidence.
  • 10. What is TDD 1. Add a test 2. Run all tests and see if the new test fails (RED) 3. Write the code (Only to make the test pass!!!) 4. Run tests 5. Refactor code 6. Repeat
  • 12. Why TDD Less bugs I like it … I feel more comfortable … … Helps to create a “GOOD” design
  • 13. Why TDD TDD changes the point of view. Forces the developer to think about the “behaviour” of the code. Talks to the developer showing what are the “difficult points” of the code. If the tests talk, we should listen them … (often we ignore them).
  • 14. Listen the test TEST(MailComposerTest, test1) { User gino{"gino", "gino@gino.it", true}; User pino{"pino", "pino@pino.it", false}; auto userRepository = UserRepository::create(); userRepository->CreateUser(gino); userRepository->CreateUser(pino); MailComposer composer; composer.SendEmail("gino@gino.it", "body one"); composer.SendEmail("pino@pino.it", "body two"); auto emailsSent = ExternalLibrary::TestEmailServer::GetEmailsSent(); ASSERT_EQ(emailsSent.size(), 1); ExternalLibrary::Email expected{"gino@gino.it", GlobalSettings::GetFromAddress(), "body one"}; ASSERT_EQ(*emailsSent.begin(), expected); }
  • 15. Listen the test class MailComposer { public: void SendEmail(std::string email, std::string body) { using namespace ExternalLibrary; auto userRepository = UserRepository::create(); auto user = userRepository->GetUserByEmail(email); if (!user.acceptEmail()) return; EmailServer::GetInstance()->SendEmail(Email{ GlobalSettings::GetFromAddress(), user.email(), body}); } };
  • 16. Listen the test It isn’t a tool problem. It’s a design problem … What is telling (screaming) the test?
  • 17. Listen the test TEST(MailComposerTest, test1) { User gino{"gino", "gino@gino.it", true}; User pino{"pino", "pino@pino.it", false}; auto userRepository = UserRepository::create(); userRepository->CreateUser(gino); userRepository->CreateUser(pino); MailComposer composer; composer.SendEmail("gino@gino.it", "body one"); composer.SendEmail("pino@pino.it", "body two"); auto emailsSent = ExternalLibrary::TestEmailServer::GetEmailsSent(); ASSERT_EQ(emailsSent.size(), 1); ExternalLibrary::Email expected{"gino@gino.it", GlobalSettings::GetFromAddress(), "body one"}; ASSERT_EQ(*emailsSent.begin(), expected); } The name doesn’t mean anything We are changing global value Singleton ?!?
  • 18. Listen the test TEST(MailComposerTest, SendEmailOnlyToUserThatAcceptEmail) { User gino{"gino", "gino@gino.it", true}; User pino{"pino", "pino@pino.it", false}; auto userRepository = UserRepository::create(); userRepository->CreateUser(gino); userRepository->CreateUser(pino); MailComposer composer( userRepository, ExternalLibrary::EmailServer::GetInstance()); composer.SendEmail("gino@gino.it", "body one"); composer.SendEmail("pino@pino.it", "body two"); auto emailsSent = ExternalLibrary::TestEmailServer::GetEmailsSent(); ASSERT_EQ(emailsSent.size(), 1); ExternalLibrary::Email expected{"gino@gino.it", GlobalSettings::GetFromAddress(), "body one"}; ASSERT_EQ(*emailsSent.begin(), expected); } Change name!!! Passing repository as parameter ... Passing Singleton as parameter
  • 19. Can we do better?!?
  • 20. TDD doesn’t mean only Unit Testing ...
  • 21. Type of tests End to End tests - Tests that work on the entire stack. Integration Test - Tests that work on some parts of the application. Unit Test - Tests that work on a single “module/function”. Why is it so important to know which type of test we are writing? Because we get different feedbacks from different types of test.
  • 23. Cycle of TDD ... 1. Add a test 2. Run all tests and see if the new test fails (RED) 3. Write the code 4. Run tests 5. Refactor code 6. Repeat
  • 25. End To End Test or Acceptance Test This type of test exercises the entire stack of the application. It remains RED until the feature is completed. Don’t write too much E2E. They are slow and fragile. Where is the design?
  • 26. How application is done (or should be)
  • 27. How application is done (or should be) Try to create a E2E test that interacts with system from the external. If it’s “impossible” try to move a little inside skipping the adapter.
  • 29. Outside-In We start writing an End to End Test that explains the feature that we want to create. We add some unit tests to shape the behaviour of the object that we want to create. We add some integration tests to verify that some parts works well together.
  • 30. Inside-Out We start writing some units test to shape the behaviour of the objects that we want to create. We add some integration tests to verify that the parts works well together. We add some End to End Tests that explain the feature that we want to create.
  • 31. My 2 cents I prefer to use Outside-In when I have to create a new feature. Outside-In requires more experienced developers/teams. I use Inside-Out when I want to introduce the TDD in a new team. I use Inside-Out when I have to add a feature and I know which objects I have to change.
  • 32. Mock
  • 33. When to use Mock? When we want to isolate one part from another. Classic example HTTP connections. We have to make some HTTP calls and manipulate the results in some ways. How can we do it?
  • 34. When to use Mock? TEST(TwitterClientTest, RetriveBioFromUser) { std::string clientId = "cleintId"; std::string clientSecret = "clientSecret"; NiceMock<MockHttpClient> mockHttpClient; EXPECT_CALL(mockHttpClient, Get("https://twitter.com/gpad619")) .WillOnce(Return("gpad_bio")); TwitterClient twitter(clientId, clientSecret, &mockHttpClient); auto bio = twitter.GetBioOf("gpad619"); EXPECT_EQ(bio, "gpad_bio"); }
  • 35. When to use Mock? We are at the boundaries of our system and we can use the mock to shape the behavior between the CORE and the adapter that talks with the external system. It’s the CORE that choose the shape of the data and how the functions should be done.
  • 36. When to use Mock? TEST(AggregationTest, SaveTheSumWhenThresholdIsReached) { NiceMock<MockPointRepository> mockPointRepository; EXPECT_CALL(mockPointRepository, Store(4)); Aggregation aggregation(4, &mockPointRepository); aggregation.Add(2); aggregation.Add(2); }
  • 37. When to use Mock? - Time TEST(AggregationTest, SaveTheEventWhenThresholdIsReached) { auto now = std::chrono::system_clock::now(); NiceMock<MockPointRepository> mockPointRepository; EXPECT_CALL(mockPointRepository, StoreEvent("Threshold Reached", now)); Aggregation aggregation(4, &mockPointRepository); aggregation.Add(2); aggregation.Add(2); }
  • 38. When to use Mock? - Time
  • 39. When to use Mock? - Time class Aggregation { int _sum; int _threshold; PointRepository *_pointRepository; public: void Add(int value) { _sum += value; if (_sum >= _threshold) { _pointRepository->Store(_sum); _pointRepository->StoreEvent("Threshold Reached", std::chrono::system_clock::now()); } } }; This is a dependency!!!
  • 40. When to use Mock? - Time TEST(AggregationTest, SaveTheEventWhenThresholdIsReached) { auto now = std::chrono::system_clock::now(); NiceMock<MockPointRepository> mockPointRepository; EXPECT_CALL(mockPointRepository, StoreEvent("Threshold Reached", now)); NiceMock<MockClock> mockClock; ON_CALL(mockClock, Now()).WillByDefault(Return(now)); Aggregation aggregation(4, &mockPointRepository, &mockClock); aggregation.Add(2); aggregation.Add(2); }
  • 41. When to use Mock? - Time class Aggregation { ...; public: Aggregation(int threshold, PointRepository *pointReposiotry, Clock *clock) ... void Add(int value) { _sum += value; if (_sum >= _threshold) { _pointRepository->Store(_sum); _pointRepository->StoreEvent("Threshold Reached", _clock->Now()); } } };
  • 42. When to use Mock? - Time How to manage a periodic task? Divide et impera.
  • 43. When to use Mock? - Time TEST(Scheduler, ExecuteTaskAfterSomeAmountOfTime) { Scheduler scheduler; bool executed = false; scheduler.ExecuteAfter( std::chrono::milliseconds(500), [&]() { executed = true; }); EXPECT_THAT(executed, WillBe(true, std::chrono::milliseconds(1000))); }
  • 44. When to use Mock? - Time TEST(Scheduler, DontExecuteTaskImmediatly) { Scheduler scheduler; bool executed = false; scheduler.ExecuteAfter( std::chrono::milliseconds(500), [&]() { executed = true; }); EXPECT_FALSE(executed); }
  • 45. WHERE to use Mock? Use the mock at the external of CORE/Domain (adapter). Isolate the CORE from the infrastructure not because we want to switch from PG to Mongo but because that libraries are not under our control.
  • 46. When to use Mock? - Interaction between objects TEST(CartTest, RetrieveDiscoutForUserWhenAddItem) { User user("gino", "g@g.it", true); NiceMock<MockTrackingSystem> mockTrackingSystem; NiceMock<MockDiscountEngine> mockDiscountEngine; EXPECT_CALL(mockDiscountEngine, GetDiscountFor(user)) .WillRepeatedly(Return(0.1)); Cart cart(user, &mockDiscountEngine, &mockTrackingSystem); cart.AddItem(Product(ProductId::New(), "Product", Money(10, "EUR"))); EXPECT_EQ(cart.GetTotal(), Money(9, "EUR")); }
  • 47. When to use Mock? - Interaction between objects TEST(CartTest, CallTrackingSystemWhenRemoveItemFromCart) { User user("gino", "g@g.it", true); Product product(ProductId::New(), "Product", Money(10, "EUR")); NiceMock<MockTrackingSystem> mockTrackingSystem; NiceMock<MockDiscountEngine> mockDiscountEngine; EXPECT_CALL(mockTrackingSystem, ProductRemoved(product)); Cart cart(user, &mockDiscountEngine, &mockTrackingSystem); cart.AddItem(product); cart.RemoveItem(product); }
  • 48. WHERE to use Mock? We can use the mock when we want to define how the object talk to each other. We can define the protocol that the object should use to talk to each other.
  • 49. When not to use Mock? Don’t use mock on Object that don’t own. TEST(MailComposerTest, TestMailComposerMock) { User gino{"gino", "gino@gino.it", true}; User pino{"pino", "pino@pino.it", false}; auto userRepository = UserRepository::create(); userRepository->CreateUser(gino); userRepository->CreateUser(pino); NiceMock<MockExternalEmailServer> mockExternalEmailServer; MailComposer composer(userRepository, &mockExternalEmailServer); ... }
  • 50. When not to use Mock? Don’t mock value objects!!! TEST(MailComposerTest, TestMailComposerMockUser) { NiceMock<MockUser> gino(); NiceMock<MockUser> pino(); EXPECT_CALL(gino, acceptEmail()).WillRepeatedly(Return(true)); EXPECT_CALL(pino, acceptEmail()).WillRepeatedly(Return(true)); auto userRepository = UserRepository::create(); MailComposer composer(userRepository, ExternalLibrary::EmailServer::GetInstance()); composer.SendEmail(gino, "body one"); composer.SendEmail(pino, "body two"); }
  • 51. TDD - Mix Everything together What is the first test to do? We could start from outside with an E2E test to enter inside our application. Or we could start inside our application adding some unit tests to some objects. Create at least one E2E for every User Story. Don’t create too much E2E they are slow and fragile.
  • 52. TDD - Mix Everything together TEST_F(AsLoggedUser, IWantSeeMyCurrentCart) { auto cart = CreateCartFor(_currentUser); auto total = GetMainWindow() ->GetCartWindowFor(_currentUser) ->GetTotal(); EXPECT_EQ(total, cart.GetTotal()); }
  • 53. TDD - Mix Everything together TEST_F(AsLoggedUser, IWantPayMyCurrentCart) { auto cart = CreateCartFor(_currentUser); auto paymentInfo = CreatePaymentInfoFor(_currentUser); auto paymentResult = GetMainWindow() ->GetPaymentWindowFor(_currentUser) ->Pay(); EXPECT_EQ(paymentResult, PaymentResult::Successful); }
  • 54. TDD - Mix Everything together The E2E remains RED until all the cycle is completed. After that we have written the E2E we go inside the CORE and start to create some unit tests.
  • 55. TDD - Mix Everything together TEST(CartTest, CalculateCartTotalWhenAddItem) { User user("gino", "g@g.it", true); NiceMock<MockTrackingSystem> mockTrackingSystem; NiceMock<MockDiscountEngine> mockDiscountEngine; Cart cart(user, &mockDiscountEngine, &mockTrackingSystem); cart.AddItem(Product(ProductId::New(), "Product1", Money(5, "EUR"))); cart.AddItem(Product(ProductId::New(), "Product2", Money(4, "EUR"))); EXPECT_EQ(cart.GetTotal(), Money(9, "EUR")); }
  • 56. TDD - Mix Everything together After we have written the unit tests for the CORE we could move to the boundaries where we should write tests for the adapter parts. The test for storage part should be written using the DB. IMHO they are more integration than unit.
  • 57. TDD - Mix Everything together TEST_F(SqlCartRepositoryTest, ReadSavedCartById) { Cart cart = BuildCartWithSomeItemsFor(_currentUser); _cartRepository.Save(cart); auto cartFromDb = _cartRepository.GetById(cart.GetId()); EXPECT_THAT(cart, IsEquivalent(cartFromDb)); }
  • 58. TDD - Mix Everything together Writing these tests BEFORE the implementation we are doing DESIGN. We are shaping the production code. The code became more “composable”. It’s more clear where are side effects (I/O, Time). It’s more clear what are the different parts of our applications.
  • 59. Recap TDD is not a Silver Bullet. TDD doesn’t give us a “good” design if we are not able to do it. TDD can help us to find some issues in our design. Listen the test, often they are screaming in pain ...
  • 60. Reference Modern C++ Programming with Test-Driven Development GOOS Clean Architecture Clean Code WELC The Rspec Book