Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Testing Asynchronous OTP
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Andrea Leopardi
September 09, 2021
Programming
1
560
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
37
gen_statem - OTP's Unsung Hero
whatyouhide
2
300
The World is a Network (and We Are Just Nodes)
whatyouhide
1
240
BEAM: The Perfect Fit for Networks
whatyouhide
1
230
Update from the Elixir team - 2022
whatyouhide
0
450
Elixir Sightseeing Tour
whatyouhide
0
460
Mint - Disrupting HTTP clients
whatyouhide
0
290
BEAM Architecture Handbook
whatyouhide
7
2.9k
The Evolution of a Language
whatyouhide
0
190
Other Decks in Programming
See All in Programming
Agent Skills Workshop - AIへの頼み方を仕組み化する
gotalab555
13
7.4k
エージェント開発初心者の僕がエージェントを作った話と今後やりたいこと
thasu0123
0
210
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
310
浮動小数の比較について
kishikawakatsumi
0
360
AIによる高速開発をどう制御するか? ガードレール設置で開発速度と品質を両立させたチームの事例
tonkotsuboy_com
7
2.6k
Lambda のコードストレージ容量に気をつけましょう
tattwan718
0
200
CSC307 Lecture 10
javiergs
PRO
1
690
Rで始めるML・LLM活用入門
wakamatsu_takumu
0
110
2026年は Rust 置き換えが流行る! / 20260220-niigata-5min-tech
girigiribauer
0
210
Beyond the Basics: Signal Forms
manfredsteyer
PRO
0
110
Go1.26 go fixをプロダクトに適用して困ったこと
kurakura0916
0
310
JPUG勉強会 OSSデータベースの内部構造を理解しよう
oga5
2
220
Featured
See All Featured
Measuring & Analyzing Core Web Vitals
bluesmoon
9
760
Optimising Largest Contentful Paint
csswizardry
37
3.6k
Git: the NoSQL Database
bkeepers
PRO
432
66k
ラッコキーワード サービス紹介資料
rakko
1
2.5M
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
140
sira's awesome portfolio website redesign presentation
elsirapls
0
170
WENDY [Excerpt]
tessaabrams
9
36k
Ruling the World: When Life Gets Gamed
codingconduct
0
160
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
170
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
130
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
110
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
9.7k
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