SlideShare a Scribd company logo
TDD is not about
testing
Bad name for good technique ...
#CodeBEAMSTO
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
#CodeBEAMSTO
Schedule
What is TDD?
Why TDD?
TDD is not (only) Unit Testing
TDD in OOP vs FP
Examples
#CodeBEAMSTO
What is TDD - History
Wikipedia - TDD
Wikipedia - Extreme Programming
Quora - Why does Kent Beck rediscover TDD
http://wiki.c2.com/?TestingFramework
Wikipedia - C2 System
#CodeBEAMSTO
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;
#CodeBEAMSTO
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.
#CodeBEAMSTO
What is TDD - History
#CodeBEAMSTO
What is TDD - History
Form 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.
#CodeBEAMSTO
What is TDD
#CodeBEAMSTO
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
#CodeBEAMSTO
Why TDD
Less bugs
I like it …
I feel more comfortable …
…
Helps to create a “GOOD” design
#CodeBEAMSTO
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).
#CodeBEAMSTO
Listen the test
defmodule MyModule do
def postpone(dest, msg) do
msg = encapsulate(msg)
time = get_delay()
Process.send_after(dest, msg, time)
end
defp encapsulate(msg) do
{:postone, msg}
end
def get_delay() do
Application.get_env(:postone, :time, 10000)
end
end
#CodeBEAMSTO
Listen the test
defmodule MyModuleTest do
use ExUnit.Case
test "postone right" do
MyModule.postpone(self(), "ciao")
assert_receive {:postone, "ciao"}, 20_000
end
end
The name doesn’t mean anything
Our test is sloooow ...
#CodeBEAMSTO
Listen the test - other smells ...
defmodule MyModuleTest do
use ExUnit.Case
test "postpone right" do
Application.put_env(:postone, :time, 1)
MyModule.postpone(self(), "ciao")
assert_receive {:postone, "ciao"}
end
test "postpone for right time ..." do
MyModule.postpone(self(), "ciao")
refute_receive {:postone, "ciao"}, 5000
end
end
Change GLOBAL value!!!!
No More isolated !!!
#CodeBEAMSTO
Listen the test
defmodule MyModuleTest do
use ExUnit.Case, async: false
import Mock
test "postone right with mock" do
with_mock(Process, [:passthrough], send_after: fn dst, msg, _ -> send(dst, msg) end) do
MyModule.postpone(self(), "ciao")
assert_receive {:postone, msg}
end
end
end
No more concurrency
Why this ?!?!
Still doesn’t work ...
This is not our module
#CodeBEAMSTO
Listen the test
It isn’t a tool problem.
It’s a design problem …
What is telling (screaming) the test?
#CodeBEAMSTO
Listen the test
defmodule MyModuleTest do
use ExUnit.Case
test "postone right" do
MyModule.postpone(self(), "ciao")
assert_receive {:postone, "ciao"}, 20_000
end
end
The name doesn’t mean anything
Our test is sloooow ...
#CodeBEAMSTO
Listen the test
defmodule MyModuleTest do
use ExUnit.Case
test "postone/1 send delayed message" do
MyModule.postpone(self(), "ciao", 0)
assert_receive {:postone, "ciao"}
end
end
Describe the behaviour of method
We can manage the behaviour of our function ...
#CodeBEAMSTO
Listen the test
defmodule MyModule do
@postpone_time Application.get_env(:postone, :time, 10000)
def postpone(dest, msg, time  @postpone_time) do
msg = encapsulate(msg)
Process.send_after(dest, msg, time)
end
defp encapsulate(msg) do
{:postone, msg}
end
end
Can we do better?!?
TDD doesn’t mean Unit Testing ...
#CodeBEAMSTO
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 important to know which type of test we are writing?
Because we get different feedbacks from different types of test.
#CodeBEAMSTO
Type of tests
#CodeBEAMSTO
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
#CodeBEAMSTO
Cycle of TDD ...
#CodeBEAMSTO
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?
#CodeBEAMSTO
How application is done (or should be)
#CodeBEAMSTO
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.
Are we creating a Java application?
#CodeBEAMSTO
OOP vs FP
OOP - We pass object reference to Object under test!
FP - We have immutability!
Elixir - We have almost always immutability!
Immutability means purity.
Purity means no side effects.
#CodeBEAMSTO
OOP vs FP
What are the instructions that make the code impure?
Everytime we make an I/O operation we aren’t pure.
Everytime we send a message.
Everytime we use the time.
#CodeBEAMSTO
OOP vs FP
What’s happen when we lost our purity?
We depend to something “external”.
We are doing at least integration test.
So ...
#CodeBEAMSTO
OOP vs FP
In OOP is quite common use mock to mock dependencies of objects and to
define the relationship between them.
In FP (IMHO) mock should be used to manage the impurity of our language.
Mock
#CodeBEAMSTO
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?
#CodeBEAMSTO
When to use Mock?
DON’T TRY THIS AT HOME!!
test "create data via https", %{id: id} do
response = create_response(201, %{key: "value"})
with_mock HTTPoison, [:passthrough], post: fn @url, _, _, _ -> {:ok, response} end do
{:ok, %{res: value}} = MyModule.execute(id)
assert value == "value"
assert called(HTTPoison.post(@url, %{id: id}, :_, :_))
end
end
#CodeBEAMSTO
When to use Mock?
Better solution
test "create data via https", %{id: id} do
with_mock RemoteData, create: fn %{id: id} -> {:ok, %{key: "value"}} end do
{:ok, %{res: "value"}} = MyModule.execute(id)
assert called(RemoteData.create(%{id: id}))
end
end”
Our module
More domain related function ...
#CodeBEAMSTO
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.
#CodeBEAMSTO
When to use Mock? - I/0
defmodule MyCoreModule do
def store_valid_data(data, limit, delta) do
content = data
|> Enum.filter(fn %{value: value} -> around(value, limit, delta) end)
|> Enum.map(fn %{value: v, comment: c} -> "value: #{v} - comment: #{c}" end)
|> Enum.join("n")
:ok = File.write(@path, content)
end
end
#CodeBEAMSTO
When to use Mock? - I/0
defmodule MyCoreModule do
def store_valid_data(data, limit, delta, storage  FileStorage) do
content = data
|> Enum.filter(fn %{value: value} -> around(value, limit, delta) end)
|> Enum.map(fn %{value: v, comment: c} -> "value: #{v} - comment: #{c}" end)
|> Enum.join("n")
:ok = storage.store(content)
end
end
#CodeBEAMSTO
When to use Mock? - I/O
defmodule MyCoreModuleTest do
use ExUnit.Case
defmodule MockStorage do
def store(content) do
send(self(), {:store, content})
:ok
end
end
test "store only valid data", %{limit: limit, delta: delta} do
valid = valid_data(limit, delta)
invalid = invalid_data(limit, delta)
content = "value: #{valid.value} - comment: #{valid.comment}"
MyCoreModule.store_valid_data(
[valid, invalid], limit, delta, MockStorage)
assert_received {:store, ^content}
end
#CodeBEAMSTO
When to use Mock? - Time
defmodule MyCoreModule do
def create_question(opts) do
%{
question: Keyword.get(opts, :q, "Sense of life?"),
response: Keyword.get(opts, :a, 42),
created_at: DateTime.utc_now()
}
end
end
#CodeBEAMSTO
When to use Mock? - Time
defmodule MyCoreModuleTest do
use ExUnit.Case
test "create questions" do
assert MyCoreModule.create_question([]) == %{
question: "Sense of life?",
response: 42,
created_at: DateTime.utc_now()
}
end
end
#CodeBEAMSTO
When to use Mock? - Time
#CodeBEAMSTO
When to use Mock? - Time
defmodule MyCoreModule do
def create_question(opts, clock  Clock) do
%{
question: Keyword.get(opts, :q, "Sense of life?"),
response: Keyword.get(opts, :a, 42),
created_at: clock.utc_now()
}
end
end
#CodeBEAMSTO
When to use Mock? - Time
test "create default questions" do
assert MyCoreModule.create_question([], MockClock) == %{
question: "Sense of life?",
response: 42,
created_at: MockClock.utc_now()
}
end
#CodeBEAMSTO
When to use Mock? - Time
#CodeBEAMSTO
When to use Mock? - Time
How to manage a periodic task?
Divide et impera.
#CodeBEAMSTO
When to use Mock? - Time
defmodule MyCoreModuleTest do
use ExUnit.Case
test "change state at every tick" do
prev = MyCoreModule.new()
next = MyCoreModule.tick(prev)
assert next.value == prev.value + 1
end
end
#CodeBEAMSTO
When to use Mock? - Time
defmodule MyCoreModuleServerTest do
use ExUnit.Case
test "call tick when receive tick" do
with_mock(MyCoreModule, tick: fn s -> s end) do
pid = MyCoreModuleServer.start_link()
send(pid, :tick)
eventually_assert(fn -> assert_called(MyCoreModule.tick(:_)) end)
end
end
end
#CodeBEAMSTO
When to use Mock? - Time
defmodule MyCoreModuleServer do
use GenServer
def init([other_args, duration]) do
state = calc_state(other_args, duration)
Process.send_after(self(), :tick, duration)
{:ok, state}
end
def handle_info(:tick, state) do
new_core = MyCoreModule.tick(state.core)
Process.send_after(self(), :tick, state.duration)
{:noreply, %{state | core: new_core}}
end
#CodeBEAMSTO
WHERE to use Mock?
Use the mock at the external of
CORE/Domain (adapter).
Try to keep the CORE pure so we
don’t have “side-effect” inside it.
#CodeBEAMSTO
When not to use Mock?
Don’t use mock on Module that don’t own.
test "create data via https", %{id: id} do
response = create_response(201, %{key: "value"})
with_mock HTTPoison, [:passthrough], post: fn @url, _, _, _ -> {:ok, response} end do
{:ok, %{res: value}} = MyModule.execute(id)
assert value == "value"
assert called(HTTPoison.post(@url, %{id: id}, :_, :_))
end
end
#CodeBEAMSTO
When not to use Mock?
Don’t use mock because otherwise “you aren’t doing unit test”
defmodule MyCoreModule1 do
def execute(data) do
data
|> Enum.map(fn -> {data.id, data.value, data} end)
|> MyCoreModule2.filter(data.filter)
|> MyCoreModule3.map(data.type)
end
end
#CodeBEAMSTO
When not to use Mock?
defmodule MyCoreModule1Test do
use ExUnit.Case
test "execute filter and map data" do
with_mocks [
{MyCoreModule2, [], filter: fn data, _level -> data end},
{MyCoreModule3, [], map: fn data, _type -> data end}
] do
MyCoreModule1.execute([%{id: 12, value: 1, filter: 10, type: OtherModule}])
assert called(MyCoreModule2.filter(:_, :_))
assert called(MyCoreModule3.map(:_, :_))
end
end
end
#CodeBEAMSTO
TDD - Mix Everything together
What is the first test to do?
We could start from an E2E test to enter inside our application.
Create at least one E2E for every User Story.
Don’t create too much E2E they are slow and fragile.
#CodeBEAMSTO
TDD - Mix Everything together
defmodule MayApp.EndToEnd.GamesTest do
use MayApp.ConnCase, async: false
describe "As Logged User" do
test "I would see my active games", %{conn: conn} do
{:ok, game} = create_active_game()
conn = get(conn, "/api/games")
assert json_response(conn, 200) == expected_response_for(game)
end
...
#CodeBEAMSTO
TDD - Mix Everything together
defmodule MayApp.EndToEnd.GamesTest do
use MayApp.ConnCase, async: false
describe "As Logged User" do
...
test "I would create a new games", %{conn: conn} do
conn = post(conn, "/api/games")
res = json_response(conn, 200)
assert %{"id" => _, "status" => "active"} = res
end
end
end
#CodeBEAMSTO
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.
The Unit Test should be PURE.
#CodeBEAMSTO
TDD - Mix Everything together
defmodule MayApp.MyCoreModuleTest do
use ExUnit.Case
test "at every tick the count is incremented" do
state = MyCoreModule.new(MockClock)
new_state = MyCoreModule.tick(state)
assert new_state.count == state.count + 1
assert new_state.last_updated_at == MockClock.utc_now()
end
...
end
#CodeBEAMSTO
TDD - Mix Everything together
defmodule MayApp.MyCoreModuleTest do
use ExUnit.Case
test "at every tick the count is incremented" do
state = MyCoreModule.new()
new_state = MyCoreModule.tick(state, now)
assert new_state.count == state.count + 1
assert new_state.last_updated_at == now
end
...
end
#CodeBEAMSTO
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.
#CodeBEAMSTO
TDD - Mix Everything together
defmodule MayApp.GameServerTest do
use ExUnit.Case, async: false
test "at every tick the state is changed" do
id = 123
game = %{id: id, state: :ready}
with_mocks [{GameStorage, load: fn ^id -> game end},
{MyCoreModule, tick: fn ^game, _ -> game end}] do
{:ok, pid} = GameServer.start_link(id, tick: :manual)
GameServer.tick(pid)
assert_called(MyCoreModule.tick(game, :_))
end
end
#CodeBEAMSTO
TDD - Mix Everything together
defmodule MayApp.GameServerTest do
use ExUnit.Case, async: false
test "at every tick the new game is stored" do
game = Game.new()
GameStorage.save_game(game)
{:ok, pid} = GameServer.start_link(game.id, tick: :manual)
GameServer.tick(pid)
eventually_assert(fn ->
new_game = GameStorage.load(game.id)
assert new_game.count == game.count + 1
end)
end
end
#CodeBEAMSTO
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.
#CodeBEAMSTO
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 ...
#CodeBEAMSTO
Reference
GOOS
Clean Architecture
Unit Test in Elixir
Mocks and explicit contracts
Property based testing with PropEr, Erlang and Elixir
Testing Elixir
End - Thanks !!!

More Related Content

What's hot

Functional Patterns with Java8 at Devoxx UK - Slides
Functional Patterns with Java8 at Devoxx UK - SlidesFunctional Patterns with Java8 at Devoxx UK - Slides
Functional Patterns with Java8 at Devoxx UK - Slides
Victor Rentea
 
Clean Pragmatic Architecture - Avoiding a Monolith
Clean Pragmatic Architecture - Avoiding a MonolithClean Pragmatic Architecture - Avoiding a Monolith
Clean Pragmatic Architecture - Avoiding a Monolith
Victor Rentea
 
Clean Code II - Dependency Injection
Clean Code II - Dependency InjectionClean Code II - Dependency Injection
Clean Code II - Dependency Injection
Theo Jungeblut
 
Don't Be Mocked by your Mocks - Best Practices using Mocks
Don't Be Mocked by your Mocks - Best Practices using MocksDon't Be Mocked by your Mocks - Best Practices using Mocks
Don't Be Mocked by your Mocks - Best Practices using Mocks
Victor Rentea
 
Clean Lambdas & Streams in Java8
Clean Lambdas & Streams in Java8Clean Lambdas & Streams in Java8
Clean Lambdas & Streams in Java8
Victor Rentea
 
Clean Code
Clean CodeClean Code
Clean Code
Victor Rentea
 
Evolving a Clean, Pragmatic Architecture - A Craftsman's Guide
Evolving a Clean, Pragmatic Architecture - A Craftsman's GuideEvolving a Clean, Pragmatic Architecture - A Craftsman's Guide
Evolving a Clean, Pragmatic Architecture - A Craftsman's Guide
Victor Rentea
 
Unit testing legacy code
Unit testing legacy codeUnit testing legacy code
Unit testing legacy code
Lars Thorup
 
Clean Code III - Software Craftsmanship
Clean Code III - Software CraftsmanshipClean Code III - Software Craftsmanship
Clean Code III - Software Craftsmanship
Theo Jungeblut
 
Battle of The Mocking Frameworks
Battle of The Mocking FrameworksBattle of The Mocking Frameworks
Battle of The Mocking Frameworks
Dror Helper
 
Testing Legacy Rails Apps
Testing Legacy Rails AppsTesting Legacy Rails Apps
Testing Legacy Rails Apps
Rabble .
 
Clean Code - Design Patterns and Best Practices at Silicon Valley Code Camp
Clean Code - Design Patterns and Best Practices at Silicon Valley Code CampClean Code - Design Patterns and Best Practices at Silicon Valley Code Camp
Clean Code - Design Patterns and Best Practices at Silicon Valley Code Camp
Theo Jungeblut
 
XPDays Ukraine: Legacy
XPDays Ukraine: LegacyXPDays Ukraine: Legacy
XPDays Ukraine: Legacy
Victor_Cr
 
Practical Test Automation Deep Dive
Practical Test Automation Deep DivePractical Test Automation Deep Dive
Practical Test Automation Deep Dive
Alan Richardson
 
Test-Driven Development (TDD)
Test-Driven Development (TDD)Test-Driven Development (TDD)
Test-Driven Development (TDD)
Brian Rasmussen
 
Refactoring legacy code driven by tests - ENG
Refactoring legacy code driven by tests - ENGRefactoring legacy code driven by tests - ENG
Refactoring legacy code driven by tests - ENG
Luca Minudel
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy Code
Naresh Jain
 
Pure Functions and Immutable Objects
Pure Functions and Immutable ObjectsPure Functions and Immutable Objects
Pure Functions and Immutable Objects
Victor Rentea
 
Coder sans peur du changement avec la meme pas mal hexagonal architecture
Coder sans peur du changement avec la meme pas mal hexagonal architectureCoder sans peur du changement avec la meme pas mal hexagonal architecture
Coder sans peur du changement avec la meme pas mal hexagonal architecture
Thomas Pierrain
 
Working Effectively with Legacy Code
Working Effectively with Legacy CodeWorking Effectively with Legacy Code
Working Effectively with Legacy Code
Orbit One - We create coherence
 

What's hot (20)

Functional Patterns with Java8 at Devoxx UK - Slides
Functional Patterns with Java8 at Devoxx UK - SlidesFunctional Patterns with Java8 at Devoxx UK - Slides
Functional Patterns with Java8 at Devoxx UK - Slides
 
Clean Pragmatic Architecture - Avoiding a Monolith
Clean Pragmatic Architecture - Avoiding a MonolithClean Pragmatic Architecture - Avoiding a Monolith
Clean Pragmatic Architecture - Avoiding a Monolith
 
Clean Code II - Dependency Injection
Clean Code II - Dependency InjectionClean Code II - Dependency Injection
Clean Code II - Dependency Injection
 
Don't Be Mocked by your Mocks - Best Practices using Mocks
Don't Be Mocked by your Mocks - Best Practices using MocksDon't Be Mocked by your Mocks - Best Practices using Mocks
Don't Be Mocked by your Mocks - Best Practices using Mocks
 
Clean Lambdas & Streams in Java8
Clean Lambdas & Streams in Java8Clean Lambdas & Streams in Java8
Clean Lambdas & Streams in Java8
 
Clean Code
Clean CodeClean Code
Clean Code
 
Evolving a Clean, Pragmatic Architecture - A Craftsman's Guide
Evolving a Clean, Pragmatic Architecture - A Craftsman's GuideEvolving a Clean, Pragmatic Architecture - A Craftsman's Guide
Evolving a Clean, Pragmatic Architecture - A Craftsman's Guide
 
Unit testing legacy code
Unit testing legacy codeUnit testing legacy code
Unit testing legacy code
 
Clean Code III - Software Craftsmanship
Clean Code III - Software CraftsmanshipClean Code III - Software Craftsmanship
Clean Code III - Software Craftsmanship
 
Battle of The Mocking Frameworks
Battle of The Mocking FrameworksBattle of The Mocking Frameworks
Battle of The Mocking Frameworks
 
Testing Legacy Rails Apps
Testing Legacy Rails AppsTesting Legacy Rails Apps
Testing Legacy Rails Apps
 
Clean Code - Design Patterns and Best Practices at Silicon Valley Code Camp
Clean Code - Design Patterns and Best Practices at Silicon Valley Code CampClean Code - Design Patterns and Best Practices at Silicon Valley Code Camp
Clean Code - Design Patterns and Best Practices at Silicon Valley Code Camp
 
XPDays Ukraine: Legacy
XPDays Ukraine: LegacyXPDays Ukraine: Legacy
XPDays Ukraine: Legacy
 
Practical Test Automation Deep Dive
Practical Test Automation Deep DivePractical Test Automation Deep Dive
Practical Test Automation Deep Dive
 
Test-Driven Development (TDD)
Test-Driven Development (TDD)Test-Driven Development (TDD)
Test-Driven Development (TDD)
 
Refactoring legacy code driven by tests - ENG
Refactoring legacy code driven by tests - ENGRefactoring legacy code driven by tests - ENG
Refactoring legacy code driven by tests - ENG
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy Code
 
Pure Functions and Immutable Objects
Pure Functions and Immutable ObjectsPure Functions and Immutable Objects
Pure Functions and Immutable Objects
 
Coder sans peur du changement avec la meme pas mal hexagonal architecture
Coder sans peur du changement avec la meme pas mal hexagonal architectureCoder sans peur du changement avec la meme pas mal hexagonal architecture
Coder sans peur du changement avec la meme pas mal hexagonal architecture
 
Working Effectively with Legacy Code
Working Effectively with Legacy CodeWorking Effectively with Legacy Code
Working Effectively with Legacy Code
 

Similar to Tdd is not about 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
 
Tdd is not about testing (C++ version)
Tdd is not about testing (C++ version)Tdd is not about testing (C++ version)
Tdd is not about testing (C++ version)
Gianluca Padovani
 
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
Paulo Clavijo
 
Test-Driven Design Insights@DevoxxBE 2023.pptx
Test-Driven Design Insights@DevoxxBE 2023.pptxTest-Driven Design Insights@DevoxxBE 2023.pptx
Test-Driven Design Insights@DevoxxBE 2023.pptx
Victor Rentea
 
Test-Driven Development In Action
Test-Driven Development In ActionTest-Driven Development In Action
Test-Driven Development In Action
Jon Kruger
 
iOS Test-Driven Development
iOS Test-Driven DevelopmentiOS Test-Driven Development
iOS Test-Driven Development
Pablo Villar
 
The First C# Project Analyzed
The First C# Project AnalyzedThe First C# Project Analyzed
The First C# Project Analyzed
PVS-Studio
 
Raising the Bar
Raising the BarRaising the Bar
Raising the Bar
Alexandru Bolboaca
 
Going open source with small teams
Going open source with small teamsGoing open source with small teams
Going open source with small teams
Jamie Thomas
 
Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...
Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...
Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...
Abdelkrim Boujraf
 
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
Dmytro Patserkovskyi
 
iOS Development at Scale @Chegg
iOS Development at Scale @CheggiOS Development at Scale @Chegg
iOS Development at Scale @Chegg
GalOrlanczyk
 
Good Coding Practices with JavaScript
Good Coding Practices with JavaScriptGood Coding Practices with JavaScript
Good Coding Practices with JavaScript
🏁 Pierre-Henry Soria 💡
 
DevSecCon SG 2018 Fabian Presentation Slides
DevSecCon SG 2018 Fabian Presentation SlidesDevSecCon SG 2018 Fabian Presentation Slides
DevSecCon SG 2018 Fabian Presentation Slides
Fab L
 
TDD Workshop UTN 2012
TDD Workshop UTN 2012TDD Workshop UTN 2012
TDD Workshop UTN 2012
Facundo Farias
 
TDD Best Practices
TDD Best PracticesTDD Best Practices
TDD Best Practices
Attila Bertók
 
How to complement TDD with static analysis
How to complement TDD with static analysisHow to complement TDD with static analysis
How to complement TDD with static analysis
PVS-Studio
 
DevSecCon Singapore 2018 - Remove developers’ shameful secrets or simply rem...
DevSecCon Singapore 2018 -  Remove developers’ shameful secrets or simply rem...DevSecCon Singapore 2018 -  Remove developers’ shameful secrets or simply rem...
DevSecCon Singapore 2018 - Remove developers’ shameful secrets or simply rem...
DevSecCon
 
Effective TDD - Less is more
Effective TDD - Less is moreEffective TDD - Less is more
Effective TDD - Less is moreBen Lau
 
TDD Walkthrough - Encryption
TDD Walkthrough - EncryptionTDD Walkthrough - Encryption
TDD Walkthrough - Encryption
PeterKha2
 

Similar to Tdd is not about 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 (C++ version)
Tdd is not about testing (C++ version)Tdd is not about testing (C++ version)
Tdd is not about testing (C++ version)
 
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 Design Insights@DevoxxBE 2023.pptx
Test-Driven Design Insights@DevoxxBE 2023.pptxTest-Driven Design Insights@DevoxxBE 2023.pptx
Test-Driven Design Insights@DevoxxBE 2023.pptx
 
Test-Driven Development In Action
Test-Driven Development In ActionTest-Driven Development In Action
Test-Driven Development In Action
 
iOS Test-Driven Development
iOS Test-Driven DevelopmentiOS Test-Driven Development
iOS Test-Driven Development
 
The First C# Project Analyzed
The First C# Project AnalyzedThe First C# Project Analyzed
The First C# Project Analyzed
 
Raising the Bar
Raising the BarRaising the Bar
Raising the Bar
 
Going open source with small teams
Going open source with small teamsGoing open source with small teams
Going open source with small teams
 
Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...
Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...
Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...
 
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
 
iOS Development at Scale @Chegg
iOS Development at Scale @CheggiOS Development at Scale @Chegg
iOS Development at Scale @Chegg
 
Good Coding Practices with JavaScript
Good Coding Practices with JavaScriptGood Coding Practices with JavaScript
Good Coding Practices with JavaScript
 
DevSecCon SG 2018 Fabian Presentation Slides
DevSecCon SG 2018 Fabian Presentation SlidesDevSecCon SG 2018 Fabian Presentation Slides
DevSecCon SG 2018 Fabian Presentation Slides
 
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
 
How to complement TDD with static analysis
How to complement TDD with static analysisHow to complement TDD with static analysis
How to complement TDD with static analysis
 
DevSecCon Singapore 2018 - Remove developers’ shameful secrets or simply rem...
DevSecCon Singapore 2018 -  Remove developers’ shameful secrets or simply rem...DevSecCon Singapore 2018 -  Remove developers’ shameful secrets or simply rem...
DevSecCon Singapore 2018 - Remove developers’ shameful secrets or simply rem...
 
Effective TDD - Less is more
Effective TDD - Less is moreEffective TDD - Less is more
Effective TDD - Less is more
 
TDD Walkthrough - Encryption
TDD Walkthrough - EncryptionTDD Walkthrough - Encryption
TDD Walkthrough - Encryption
 

More from Gianluca Padovani

A Gentle introduction to microservices
A Gentle introduction to microservicesA Gentle introduction to microservices
A Gentle introduction to microservices
Gianluca 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 Elixir
Gianluca 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 system
Gianluca Padovani
 
Beam way of life
Beam way of lifeBeam way of life
Beam way of life
Gianluca Padovani
 
Cook your KV
Cook your KVCook your KV
Cook your KV
Gianluca Padovani
 
System integration through queues
System integration through queuesSystem integration through queues
System integration through queues
Gianluca Padovani
 
Beam me up, Scotty
Beam me up, ScottyBeam me up, Scotty
Beam me up, Scotty
Gianluca Padovani
 
Docker e git lab
Docker e git labDocker e git lab
Docker e git lab
Gianluca Padovani
 
La mia prima lezione di pozioni
La mia prima lezione di pozioniLa mia prima lezione di pozioni
La mia prima lezione di pozioni
Gianluca 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 2015
Gianluca 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
 
OOP vs COP
OOP vs COPOOP vs COP
OOP vs COP
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

Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Globus
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
Google
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
Globus
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
Ortus Solutions, Corp
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
NYGGS Automation Suite
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
Globus
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
wottaspaceseo
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
Globus
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
Georgi Kodinov
 
RISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent EnterpriseRISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent Enterprise
Srikant77
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
Ortus Solutions, Corp
 
Accelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with PlatformlessAccelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with Platformless
WSO2
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus
 
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Shahin Sheidaei
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
Juraj Vysvader
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
Paco van Beckhoven
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Anthony Dahanne
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
vrstrong314
 

Recently uploaded (20)

Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
 
RISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent EnterpriseRISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent Enterprise
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
 
Accelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with PlatformlessAccelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with Platformless
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
 
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
 

Tdd is not about testing

  • 1. TDD is not about testing Bad name for good technique ...
  • 2. #CodeBEAMSTO 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. #CodeBEAMSTO Schedule What is TDD? Why TDD? TDD is not (only) Unit Testing TDD in OOP vs FP Examples
  • 4. #CodeBEAMSTO 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. #CodeBEAMSTO 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. #CodeBEAMSTO 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.
  • 8. #CodeBEAMSTO What is TDD - History Form 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. #CodeBEAMSTO 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. #CodeBEAMSTO Why TDD Less bugs I like it … I feel more comfortable … … Helps to create a “GOOD” design
  • 13. #CodeBEAMSTO 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. #CodeBEAMSTO Listen the test defmodule MyModule do def postpone(dest, msg) do msg = encapsulate(msg) time = get_delay() Process.send_after(dest, msg, time) end defp encapsulate(msg) do {:postone, msg} end def get_delay() do Application.get_env(:postone, :time, 10000) end end
  • 15. #CodeBEAMSTO Listen the test defmodule MyModuleTest do use ExUnit.Case test "postone right" do MyModule.postpone(self(), "ciao") assert_receive {:postone, "ciao"}, 20_000 end end The name doesn’t mean anything Our test is sloooow ...
  • 16. #CodeBEAMSTO Listen the test - other smells ... defmodule MyModuleTest do use ExUnit.Case test "postpone right" do Application.put_env(:postone, :time, 1) MyModule.postpone(self(), "ciao") assert_receive {:postone, "ciao"} end test "postpone for right time ..." do MyModule.postpone(self(), "ciao") refute_receive {:postone, "ciao"}, 5000 end end Change GLOBAL value!!!! No More isolated !!!
  • 17. #CodeBEAMSTO Listen the test defmodule MyModuleTest do use ExUnit.Case, async: false import Mock test "postone right with mock" do with_mock(Process, [:passthrough], send_after: fn dst, msg, _ -> send(dst, msg) end) do MyModule.postpone(self(), "ciao") assert_receive {:postone, msg} end end end No more concurrency Why this ?!?! Still doesn’t work ... This is not our module
  • 18. #CodeBEAMSTO Listen the test It isn’t a tool problem. It’s a design problem … What is telling (screaming) the test?
  • 19. #CodeBEAMSTO Listen the test defmodule MyModuleTest do use ExUnit.Case test "postone right" do MyModule.postpone(self(), "ciao") assert_receive {:postone, "ciao"}, 20_000 end end The name doesn’t mean anything Our test is sloooow ...
  • 20. #CodeBEAMSTO Listen the test defmodule MyModuleTest do use ExUnit.Case test "postone/1 send delayed message" do MyModule.postpone(self(), "ciao", 0) assert_receive {:postone, "ciao"} end end Describe the behaviour of method We can manage the behaviour of our function ...
  • 21. #CodeBEAMSTO Listen the test defmodule MyModule do @postpone_time Application.get_env(:postone, :time, 10000) def postpone(dest, msg, time @postpone_time) do msg = encapsulate(msg) Process.send_after(dest, msg, time) end defp encapsulate(msg) do {:postone, msg} end end
  • 22. Can we do better?!?
  • 23. TDD doesn’t mean Unit Testing ...
  • 24. #CodeBEAMSTO 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 important to know which type of test we are writing? Because we get different feedbacks from different types of test.
  • 26. #CodeBEAMSTO 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
  • 28. #CodeBEAMSTO 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?
  • 29. #CodeBEAMSTO How application is done (or should be)
  • 30. #CodeBEAMSTO 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.
  • 31. Are we creating a Java application?
  • 32. #CodeBEAMSTO OOP vs FP OOP - We pass object reference to Object under test! FP - We have immutability! Elixir - We have almost always immutability! Immutability means purity. Purity means no side effects.
  • 33. #CodeBEAMSTO OOP vs FP What are the instructions that make the code impure? Everytime we make an I/O operation we aren’t pure. Everytime we send a message. Everytime we use the time.
  • 34. #CodeBEAMSTO OOP vs FP What’s happen when we lost our purity? We depend to something “external”. We are doing at least integration test. So ...
  • 35. #CodeBEAMSTO OOP vs FP In OOP is quite common use mock to mock dependencies of objects and to define the relationship between them. In FP (IMHO) mock should be used to manage the impurity of our language.
  • 36. Mock
  • 37. #CodeBEAMSTO 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?
  • 38. #CodeBEAMSTO When to use Mock? DON’T TRY THIS AT HOME!! test "create data via https", %{id: id} do response = create_response(201, %{key: "value"}) with_mock HTTPoison, [:passthrough], post: fn @url, _, _, _ -> {:ok, response} end do {:ok, %{res: value}} = MyModule.execute(id) assert value == "value" assert called(HTTPoison.post(@url, %{id: id}, :_, :_)) end end
  • 39. #CodeBEAMSTO When to use Mock? Better solution test "create data via https", %{id: id} do with_mock RemoteData, create: fn %{id: id} -> {:ok, %{key: "value"}} end do {:ok, %{res: "value"}} = MyModule.execute(id) assert called(RemoteData.create(%{id: id})) end end” Our module More domain related function ...
  • 40. #CodeBEAMSTO 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.
  • 41. #CodeBEAMSTO When to use Mock? - I/0 defmodule MyCoreModule do def store_valid_data(data, limit, delta) do content = data |> Enum.filter(fn %{value: value} -> around(value, limit, delta) end) |> Enum.map(fn %{value: v, comment: c} -> "value: #{v} - comment: #{c}" end) |> Enum.join("n") :ok = File.write(@path, content) end end
  • 42. #CodeBEAMSTO When to use Mock? - I/0 defmodule MyCoreModule do def store_valid_data(data, limit, delta, storage FileStorage) do content = data |> Enum.filter(fn %{value: value} -> around(value, limit, delta) end) |> Enum.map(fn %{value: v, comment: c} -> "value: #{v} - comment: #{c}" end) |> Enum.join("n") :ok = storage.store(content) end end
  • 43. #CodeBEAMSTO When to use Mock? - I/O defmodule MyCoreModuleTest do use ExUnit.Case defmodule MockStorage do def store(content) do send(self(), {:store, content}) :ok end end test "store only valid data", %{limit: limit, delta: delta} do valid = valid_data(limit, delta) invalid = invalid_data(limit, delta) content = "value: #{valid.value} - comment: #{valid.comment}" MyCoreModule.store_valid_data( [valid, invalid], limit, delta, MockStorage) assert_received {:store, ^content} end
  • 44. #CodeBEAMSTO When to use Mock? - Time defmodule MyCoreModule do def create_question(opts) do %{ question: Keyword.get(opts, :q, "Sense of life?"), response: Keyword.get(opts, :a, 42), created_at: DateTime.utc_now() } end end
  • 45. #CodeBEAMSTO When to use Mock? - Time defmodule MyCoreModuleTest do use ExUnit.Case test "create questions" do assert MyCoreModule.create_question([]) == %{ question: "Sense of life?", response: 42, created_at: DateTime.utc_now() } end end
  • 46. #CodeBEAMSTO When to use Mock? - Time
  • 47. #CodeBEAMSTO When to use Mock? - Time defmodule MyCoreModule do def create_question(opts, clock Clock) do %{ question: Keyword.get(opts, :q, "Sense of life?"), response: Keyword.get(opts, :a, 42), created_at: clock.utc_now() } end end
  • 48. #CodeBEAMSTO When to use Mock? - Time test "create default questions" do assert MyCoreModule.create_question([], MockClock) == %{ question: "Sense of life?", response: 42, created_at: MockClock.utc_now() } end
  • 49. #CodeBEAMSTO When to use Mock? - Time
  • 50. #CodeBEAMSTO When to use Mock? - Time How to manage a periodic task? Divide et impera.
  • 51. #CodeBEAMSTO When to use Mock? - Time defmodule MyCoreModuleTest do use ExUnit.Case test "change state at every tick" do prev = MyCoreModule.new() next = MyCoreModule.tick(prev) assert next.value == prev.value + 1 end end
  • 52. #CodeBEAMSTO When to use Mock? - Time defmodule MyCoreModuleServerTest do use ExUnit.Case test "call tick when receive tick" do with_mock(MyCoreModule, tick: fn s -> s end) do pid = MyCoreModuleServer.start_link() send(pid, :tick) eventually_assert(fn -> assert_called(MyCoreModule.tick(:_)) end) end end end
  • 53. #CodeBEAMSTO When to use Mock? - Time defmodule MyCoreModuleServer do use GenServer def init([other_args, duration]) do state = calc_state(other_args, duration) Process.send_after(self(), :tick, duration) {:ok, state} end def handle_info(:tick, state) do new_core = MyCoreModule.tick(state.core) Process.send_after(self(), :tick, state.duration) {:noreply, %{state | core: new_core}} end
  • 54. #CodeBEAMSTO WHERE to use Mock? Use the mock at the external of CORE/Domain (adapter). Try to keep the CORE pure so we don’t have “side-effect” inside it.
  • 55. #CodeBEAMSTO When not to use Mock? Don’t use mock on Module that don’t own. test "create data via https", %{id: id} do response = create_response(201, %{key: "value"}) with_mock HTTPoison, [:passthrough], post: fn @url, _, _, _ -> {:ok, response} end do {:ok, %{res: value}} = MyModule.execute(id) assert value == "value" assert called(HTTPoison.post(@url, %{id: id}, :_, :_)) end end
  • 56. #CodeBEAMSTO When not to use Mock? Don’t use mock because otherwise “you aren’t doing unit test” defmodule MyCoreModule1 do def execute(data) do data |> Enum.map(fn -> {data.id, data.value, data} end) |> MyCoreModule2.filter(data.filter) |> MyCoreModule3.map(data.type) end end
  • 57. #CodeBEAMSTO When not to use Mock? defmodule MyCoreModule1Test do use ExUnit.Case test "execute filter and map data" do with_mocks [ {MyCoreModule2, [], filter: fn data, _level -> data end}, {MyCoreModule3, [], map: fn data, _type -> data end} ] do MyCoreModule1.execute([%{id: 12, value: 1, filter: 10, type: OtherModule}]) assert called(MyCoreModule2.filter(:_, :_)) assert called(MyCoreModule3.map(:_, :_)) end end end
  • 58. #CodeBEAMSTO TDD - Mix Everything together What is the first test to do? We could start from an E2E test to enter inside our application. Create at least one E2E for every User Story. Don’t create too much E2E they are slow and fragile.
  • 59. #CodeBEAMSTO TDD - Mix Everything together defmodule MayApp.EndToEnd.GamesTest do use MayApp.ConnCase, async: false describe "As Logged User" do test "I would see my active games", %{conn: conn} do {:ok, game} = create_active_game() conn = get(conn, "/api/games") assert json_response(conn, 200) == expected_response_for(game) end ...
  • 60. #CodeBEAMSTO TDD - Mix Everything together defmodule MayApp.EndToEnd.GamesTest do use MayApp.ConnCase, async: false describe "As Logged User" do ... test "I would create a new games", %{conn: conn} do conn = post(conn, "/api/games") res = json_response(conn, 200) assert %{"id" => _, "status" => "active"} = res end end end
  • 61. #CodeBEAMSTO 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. The Unit Test should be PURE.
  • 62. #CodeBEAMSTO TDD - Mix Everything together defmodule MayApp.MyCoreModuleTest do use ExUnit.Case test "at every tick the count is incremented" do state = MyCoreModule.new(MockClock) new_state = MyCoreModule.tick(state) assert new_state.count == state.count + 1 assert new_state.last_updated_at == MockClock.utc_now() end ... end
  • 63. #CodeBEAMSTO TDD - Mix Everything together defmodule MayApp.MyCoreModuleTest do use ExUnit.Case test "at every tick the count is incremented" do state = MyCoreModule.new() new_state = MyCoreModule.tick(state, now) assert new_state.count == state.count + 1 assert new_state.last_updated_at == now end ... end
  • 64. #CodeBEAMSTO 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.
  • 65. #CodeBEAMSTO TDD - Mix Everything together defmodule MayApp.GameServerTest do use ExUnit.Case, async: false test "at every tick the state is changed" do id = 123 game = %{id: id, state: :ready} with_mocks [{GameStorage, load: fn ^id -> game end}, {MyCoreModule, tick: fn ^game, _ -> game end}] do {:ok, pid} = GameServer.start_link(id, tick: :manual) GameServer.tick(pid) assert_called(MyCoreModule.tick(game, :_)) end end
  • 66. #CodeBEAMSTO TDD - Mix Everything together defmodule MayApp.GameServerTest do use ExUnit.Case, async: false test "at every tick the new game is stored" do game = Game.new() GameStorage.save_game(game) {:ok, pid} = GameServer.start_link(game.id, tick: :manual) GameServer.tick(pid) eventually_assert(fn -> new_game = GameStorage.load(game.id) assert new_game.count == game.count + 1 end) end end
  • 67. #CodeBEAMSTO 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.
  • 68. #CodeBEAMSTO 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 ...
  • 69. #CodeBEAMSTO Reference GOOS Clean Architecture Unit Test in Elixir Mocks and explicit contracts Property based testing with PropEr, Erlang and Elixir Testing Elixir