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
Andrea Leopardi
September 09, 2021
Programming
1
520
Testing Asynchronous OTP
Andrea Leopardi
September 09, 2021
Tweet
Share
More Decks by Andrea Leopardi
See All by Andrea Leopardi
gen_statem - OTP's Unsung Hero
whatyouhide
2
250
The World is a Network (and We Are Just Nodes)
whatyouhide
1
220
BEAM: The Perfect Fit for Networks
whatyouhide
1
200
Update from the Elixir team - 2022
whatyouhide
0
410
Elixir Sightseeing Tour
whatyouhide
0
430
Mint - Disrupting HTTP clients
whatyouhide
0
250
BEAM Architecture Handbook
whatyouhide
7
2.8k
The Evolution of a Language
whatyouhide
0
160
Elixir - functional, concurrent, distributed programming for the rest of us
whatyouhide
2
340
Other Decks in Programming
See All in Programming
AIに安心して任せるためにTypeScriptで一意な型を作ろう
arfes0e2b3c
0
330
0から始めるモジュラーモノリス-クリーンなモノリスを目指して
sushi0120
0
250
「次に何を学べばいいか分からない」あなたへ──若手エンジニアのための学習地図
panda_program
3
720
可変性を制する設計: 構造と振る舞いから考える概念モデリングとその実装
a_suenami
10
1.6k
Claude Code と OpenAI o3 で メタデータ情報を作る
laket
0
110
LLMは麻雀を知らなすぎるから俺が教育してやる
po3rin
3
2k
バイブコーディングの正体——AIエージェントはソフトウェア開発を変えるか?
stakaya
5
790
コーディングは技術者(エンジニア)の嗜みでして / Learning the System Development Mindset from Rock Lady
mackey0225
2
220
React 使いじゃなくても知っておきたい教養としての React
oukayuka
18
5.4k
MCP連携で加速するAI駆動開発/mcp integration accelerates ai-driven-development
bpstudy
0
280
Comparing decimals in Swift Testing
417_72ki
0
160
Constant integer division faster than compiler-generated code
herumi
2
430
Featured
See All Featured
Practical Orchestrator
shlominoach
190
11k
GitHub's CSS Performance
jonrohan
1031
460k
Fireside Chat
paigeccino
38
3.6k
Measuring & Analyzing Core Web Vitals
bluesmoon
8
540
It's Worth the Effort
3n
185
28k
Thoughts on Productivity
jonyablonski
69
4.8k
Typedesign – Prime Four
hannesfritz
42
2.7k
Producing Creativity
orderedlist
PRO
347
40k
Bootstrapping a Software Product
garrettdimon
PRO
307
110k
Unsuck your backbone
ammeep
671
58k
Why You Should Never Use an ORM
jnunemaker
PRO
58
9.5k
BBQ
matthewcrist
89
9.8k
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