Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Testing Asynchronous OTP
Search
Andrea Leopardi
September 09, 2021
Programming
1
540
Testing Asynchronous OTP
Andrea Leopardi
September 09, 2021
Tweet
Share
More Decks by Andrea Leopardi
See All by Andrea Leopardi
The Umbrella and the Range
whatyouhide
0
23
gen_statem - OTP's Unsung Hero
whatyouhide
2
280
The World is a Network (and We Are Just Nodes)
whatyouhide
1
230
BEAM: The Perfect Fit for Networks
whatyouhide
1
210
Update from the Elixir team - 2022
whatyouhide
0
430
Elixir Sightseeing Tour
whatyouhide
0
450
Mint - Disrupting HTTP clients
whatyouhide
0
270
BEAM Architecture Handbook
whatyouhide
7
2.9k
The Evolution of a Language
whatyouhide
0
170
Other Decks in Programming
See All in Programming
Herb to ReActionView: A New Foundation for the View Layer @ San Francisco Ruby Conference 2025
marcoroth
0
240
MAP, Jigsaw, Code Golf 振り返り会 by 関東Kaggler会|Jigsaw 15th Solution
hasibirok0
0
210
Developing static sites with Ruby
okuramasafumi
0
150
AIエンジニアリングのご紹介 / Introduction to AI Engineering
rkaga
3
1.1k
TUIライブラリつくってみた / i-just-make-TUI-library
kazto
1
320
【CA.ai #3】ワークフローから見直すAIエージェント — 必要な場面と“選ばない”判断
satoaoaka
0
220
Evolving NEWT’s TypeScript Backend for the AI-Driven Era
xpromx
0
270
俺流レスポンシブコーディング 2025
tak_dcxi
13
7.9k
251126 TestState APIってなんだっけ?Step Functionsテストどう変わる?
east_takumi
0
300
CSC305 Lecture 15
javiergs
PRO
0
250
令和最新版Android Studioで化石デバイス向けアプリを作る
arkw
0
230
Navigation 3: 적응형 UI를 위한 앱 탐색
fornewid
1
150
Featured
See All Featured
Side Projects
sachag
455
43k
Music & Morning Musume
bryan
46
7k
GraphQLとの向き合い方2022年版
quramy
50
14k
Balancing Empowerment & Direction
lara
5
780
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.2k
Designing for humans not robots
tammielis
254
26k
Why Our Code Smells
bkeepers
PRO
340
57k
Done Done
chrislema
186
16k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
9.8k
GraphQLの誤解/rethinking-graphql
sonatard
73
11k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
1.6k
Transcript
None
None
None
None
None
None
None
None
None
None
None
None
None
None
None
None
None
None
None
None
None
defmodule RollingAverage do use GenServer def start_link(limit), do: # ...
def add(pid, n), do: # ... def average(pid), do: # ... end
None
None
test "add/2" do {:ok, pid} = RollingAverage.start_link() RollingAverage.add(pid, 3) #
Now what? end
None
test "add/2 and average/1" do {:ok, pid} = RollingAverage.start_link(2) RollingAverage.add(pid,
3) RollingAverage.add(pid, 4) assert RollingAverage.average(pid) == 3.5 RollingAverage.add(pid, 5) assert RollingAverage.average(pid) == 4.5 end
None
defmodule RollingList do def new(limit), do: {limit, []} def add({limit,
list}, n), do: # ... def average({_limit, list}), do: # ... end
test "add/2" do rolling_list = RollingList.new(2) assert RollingList.add(rolling_list, 3) ==
{_limit = 2, [3]} end
None
test "add/2" do {:ok, pid} = RollingAverage.start_link(2) RollingAverage.add(pid, 3) state
= :sys.get_state(pid) assert state == {_limit = 2, [3]} end
None
None
test "add/2 and average/1" do {:ok, pid} = start_supervised( {RollingAverage,
_limit = 2} ) # Same as before end
None
def background_work do Task.start(fn -> do_something() end) end
None
None
def background_work(parent, ref) do Task.start(fn -> do_something() send(parent, {ref, :done})
end) end
test "background_work/0" do ref = make_ref() background_work(self(), ref) assert_receive {^ref,
:done} end
None
def background_work do Task.start(fn -> :ok = twitter_module.post() end) end
test "background_work/0" do parent = self() ref = make_ref() Mox.expect(TwitterMock,
:post, fn -> send(parent, ref) :ok end) background_work() assert_receive ^ref end
None
defmodule WeatherChecker do use GenServer def init(_) do :timer.send_interval(5000, self(),
:tick) end def handle_info(:tick, _) do check_weather() end end
test "checking weather periodically" do {:ok, _pid} = WeatherChecker.start_link() Process.sleep(5000
* 1.5) assert weather_checked?() end
None
defmodule WeatherChecker do use GenServer def init(_) do :timer.send_interval(5000, self(),
:tick) end def tick(pid), do: send(pid, :tick) def handle_info(:tick, _) do check_weather() end end
test "checking weather periodically" do {:ok, pid} = WeatherChecker.start_link() WeatherChecker.tick(pid)
assert weather_checked?() end
defmodule WeatherChecker do use GenServer def init(:interval) do :timer.send_interval(5000, self(),
:tick) end def init(:manual) do # No send_interval end end
None
@mix_env Mix.env() def start(_type, _args) do Supervisor.start_link(children(@mix_env), ...) end defp
children(:test), do: [...] defp children(_env), do: [WeatherChecker | ...]
None
None
None
None
test "cleanup after crashes" do Process.flag(:trap_exit, true) {:ok, pid} =
start_supervised(MyServer) Process.exit(pid, :kill) assert cleanup_successful?() end
None
None
None
None
None
None
None
None
None
None