Skip to content

Instantly share code, notes, and snippets.

@koduki
Created November 16, 2019 07:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save koduki/fb15ca78d6715fa60f01306382e1efff to your computer and use it in GitHub Desktop.
Save koduki/fb15ca78d6715fa60f01306382e1efff to your computer and use it in GitHub Desktop.
Elixirで書いてみた簡易な負荷テストツール
defmodule LoadGenerator do
import AssertionHelper
import LogHelper
import RestHelper
def run(users_num) do
Enum.map(1..users_num, fn(x) -> Task.async(fn -> make_user() end)end)
|> Enum.map(fn(task) -> Task.await(task, 1_000_000) end)
end
def make_user() do
accountNo = req_origination()
# run test senario
loop_count = :rand.uniform(10)
IO.puts("loop count: #{loop_count}")
senario001(0, 0, loop_count, accountNo)
end
def senario001(count, sum, loop_count, accountNo) when loop_count > 0 do
# pay
amount1 = :rand.uniform(100_000)
transactionId1 = req_authorize(accountNo, amount1)
amount2 = :rand.uniform(10_000)
transactionId2 = req_authorize(accountNo, amount2)
# show summary
body = req_summary(accountNo, 11)
assert = assert_template(body)
# validate
count = count + 2
sum = sum + amount1 + amount2
r = it("test result", [
assert.("accountNo", :should_be, accountNo),
assert.("count", :should_be, count),
assert.("summary", :should_be, sum)
])
interval = :rand.uniform(2000)
:timer.sleep(interval)
senario001(count, sum, loop_count - 1, accountNo) ++ [r]
end
def senario001(count, sum, loop_count, accountNo) do
[]
end
def req_origination do
# origination
{t, {:http_ok, body}} = post("http://app:8080/account/create", [])
body["accountNo"]
end
def req_authorize(accountNo, amount) do
req = Jason.encode!(%{"accountNo" => accountNo, "amount" => amount, "usedDateTime" => "2019-11-15T06:51:19.918Z"})
{t, {:http_ok, body}} = post("http://app:8080/payment/authorize", req)
body["transactionId"]
end
def req_summary(accountNo, usedMonth) do
{t, {:http_ok, r}} = get("http://app:8080/account/#{accountNo}/summary/#{usedMonth}", [])
r
end
end
defmodule AssertionHelper do
def assert_template(r) do
fn (key, operation, expectation) -> {"#{key} should be #{expectation}", r[key] == expectation} end
end
def it(title, actuals) do
{
Enum.all?(actuals, fn(x) -> elem(x,1) end),
Enum.into(actuals, %{})
}
end
end
defmodule LogHelper do
def log(message) do
Task.async(fn -> IO.inspect(message) end)
end
end
defmodule RestHelper do
import LogHelper
def get(url, req) do
{_,s}=DateTime.now("Etc/UTC")
{t, r} = :timer.tc(fn ->
case HTTPoison.get(url, req, []) do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} -> {:http_ok, Jason.decode!(body)}
_ -> {:error, nil}
end
end)
{_,e}=DateTime.now("Etc/UTC")
log({(if t <= 3_000_000, do: :ok, else: :timeout), elem(r, 0), [url: url, method: :get, response: t, start_time: s, end_time: e]})
{t, r}
end
def post(url, req) do
{_,s}=DateTime.now("Etc/UTC")
{t, r} = :timer.tc(fn ->
case HTTPoison.post(url, req, [{"Content-Type", "application/json"}]) do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} -> {:http_ok, Jason.decode!(body)}
_ -> {:http_error, nil}
end
end)
{_,e}=DateTime.now("Etc/UTC")
log({(if t <= 3_000_000, do: :ok, else: :timeout), elem(r, 0), [url: url, method: :post, response: t, start_time: s, end_time: e]})
{t, r}
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment