我写了这个测试用例:
assert_raise ArgumentError, myFn(a,b)
Run Code Online (Sandbox Code Playgroud)
但它没有以我期望的方式评估.myFn引发一个ArgumentError(do: raise ArgumentError),但它没有被捕获assert_raise.
文档中的示例工作得很好:
assert_raise ArithmeticError, fn ->
1 + "test"
end
Run Code Online (Sandbox Code Playgroud)
从文档:
assert_raise(exception, function)
断言exception在function执行期间引发.返回已获救的异常,否则失败
我猜测在我的测试用例中,首先评估参数.但是我该怎么写呢?
我想测试一个与主机系统交互的Elixir模块,并且具有副作用的方法.对于这个问题并保持简短,假设它是几个目录的创建.这些目录当然应该在运行测试后删除,如果测试(很长时间)由于任何原因(坏的模块代码,错误的测试代码等)而失败.
我想知道如何最好/最优雅地解决这个清理步骤.我查看了ExUnit.Callbacks.on_exit/2的文档,但它的示例仅用于设置和简单拆解(不涉及传递状态).我也在线搜索,但没有发现任何有用的东西,所以可能是我的想法本身并不好 - 我也愿意接受重构问题的建议.
defmodule SimpleTest do
use ExUnit.Case
setup_all do
ts = Time.utc_now |> Time.to_string
{:ok, [timestamp: ts]}
# paths to be cleaned are not yet known here
end
test "first test", context do
path = "/tmp/dir" <> context[:timestamp]
assert :ok == SimpleModule.mkdir(path)
assert :eexist == SimpleModule.mkdir(path)
# [path] should be passed on to cleanup
end
test "second test", context do
path = "/tmp/dir" <> context[:timestamp]
path2 = "/tmp/dir2" <> context[:timestamp]
SimpleModule.mkdir(path)
SimpleModule.mkdir(path2)
assert File.exists?(path) …Run Code Online (Sandbox Code Playgroud) 我有一个身份验证插件,我想测试我的控制器.问题是这个插头中的线路有
user_id = get_session(conn, :user_id)
Run Code Online (Sandbox Code Playgroud)
当我使用这种方法时,它总是零(我以前使用过脏黑客,但我不想再这样做了):
@session Plug.Session.init([
store: :cookie,
key: "_app",
encryption_salt: "secret",
signing_salt: "secret",
encrypt: false
])
user = MyApp.Factory.create(:user)
conn()
|> put_req_header("accept", "application/vnd.api+json")
|> put_req_header("content-type", "application/vnd.api+json")
|> Map.put(:secret_key_base, String.duplicate("abcdefgh", 8))
|> Plug.Session.call(@session)
|> fetch_session
|> put_session(:user_id, user.id)
Run Code Online (Sandbox Code Playgroud)
我正在使用此conn发送补丁请求,其会话user_id为nil.IO.puts conn在我的插件中的结果:
%Plug.Conn{adapter: {Plug.Adapters.Test.Conn, :...}, assigns: %{},
before_send: [#Function<0.111117999/1 in Plug.Session.before_send/2>,
#Function<0.110103833/1 in JaSerializer.ContentTypeNegotiation.set_content_type/2>,
#Function<1.55011211/1 in Plug.Logger.call/2>,
#Function<0.111117999/1 in Plug.Session.before_send/2>], body_params: %{},
cookies: %{}, halted: false, host: "www.example.com", method: "PATCH",
owner: #PID<0.349.0>,
params: %{"data" => %{"attributes" => %{"action" …Run Code Online (Sandbox Code Playgroud) 我正试图IEx.pry在测试中启动.但是我无法在iex会话中运行测试.请注意,我没有使用mix.
ExUnit.start
defmodule Calc do
def add(a,b) do
a + b
end
end
defmodule TheTest do
use ExUnit.Case
test "adds two numbers" do
require IEx
IEx.pry
assert Calc.add(1, 2) == 3
end
end
Run Code Online (Sandbox Code Playgroud)
我试着用ExUnit.run挂起来运行它并最终超时:
manuel@laptop:~/exercism/elixir/nucleotide-count$ iex test.exs
Erlang/OTP 18 [erts-7.3] [source] [64-bit] [smp:4:4] [async-threads:10] [kernel-poll:false]
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> ExUnit.run
** (exit) exited in: GenServer.call(ExUnit.Server, {:take_async_cases, 8}, 60000)
** (EXIT) time out
(elixir) lib/gen_server.ex:604: GenServer.call/3
(ex_unit) …Run Code Online (Sandbox Code Playgroud) 我正在进行一个接收大量消息的频道测试.我可能会在安装过程中收到一条消息,调整某些状态,然后我想assert(或refute)发送该消息的另一个副本.我想我可以通过在导致触发第二条消息的事件之前清除邮箱来完成此操作.如何清除channelcase邮箱?
编辑,我已经通过assert_push所有旧邮件完成了我的需求,这些邮件将它们从邮箱中清除.这种方法效果很好但如果有多条消息会非常不方便
我在elixir应用程序中有一个方法,比方说Some.Module.func/1,它会返回两个数字的元组.我在ExUnit中编写测试,只需要测试元组中的第一个元素,而不是真正关心第二个元素.
到目前为止,我已经尝试过这样做:
test "some method" do
assert Some.Module.func(45) == {54, _}
end
Run Code Online (Sandbox Code Playgroud)
但是我在运行测试时遇到了这个错误:
Compiled lib/some.ex
Generated some app
** (CompileError) test/some_test.exs:7: unbound variable _
(stdlib) lists.erl:1353: :lists.mapfoldl/3
(stdlib) lists.erl:1354: :lists.mapfoldl/3
Run Code Online (Sandbox Code Playgroud)
为什么这不起作用,如何在测试中忽略不需要的结果?
我正在测试函数的返回值.两者中哪一个是首选方式?
test "extra verbose, using assert" do
{:error, reason} = MyModule.my_fun
assert reason == :nope
end
test "using pattern matching only" do
{:error, :nope} = MyModule.my_fun
end
Run Code Online (Sandbox Code Playgroud)
我喜欢第一个,因为我现在不需要测试需要一个assert语句,运行测试时的错误信息更具描述性.Otoh,MatchError带行号也应该足够了.
我们试图在一个完全干净的 dets 环境中运行每个测试,每个测试负责自己的设置。我们遇到了无法在测试之间完全删除目录的问题。
我们如何重置dets?我们是否错误地认为吹走整个目录并重新启动应用程序就足够了?在运行之间删除所有记录是否更好?
认为:
async: true 未设置任何测试。dets 是必须的示例代码:
setup do
#clean up anything that wasn't already clean (failed teardown, etc)
TestSetup.teardown_dets(:myappatom, "dets")
on_exit fn ->
TestSetup.teardown_dets(:myappatom, "dets")
Application.ensure_all_started(:myappatom)
Process.sleep(300)
end
end
Run Code Online (Sandbox Code Playgroud)
和拆卸功能的胆量......
def teardown_dets(application_atom, directory) when is_bitstring(directory) do
teardown_dets(application_atom, [directory])
end
def teardown_dets(application_atom, directories)
when is_atom(application_atom) and is_list(directories)
do
#stop the applications completely
Application.stop(application_atom)
#blow away all dets while the application is stopped
try do
directories
|> Enum.map(&File.rm_rf(&1))
rescue
error …Run Code Online (Sandbox Code Playgroud) 在 Ruby 中,特别是 RSpec,您可以告诉测试运行器在第一个未通过命令行标志的测试中中止--fail-fast。这有助于避免在连续修复大量测试时浪费时间或失去焦点,例如在进行测试驱动或行为驱动的开发时。
现在在 ExUnit 的 Elixir 上,我正在寻找一种方法来做到这一点。有没有办法做到这一点?
为了在失败的集成测试期间进行调试,我希望仍然能够看到我的应用程序日志.是否有一个命令可以传递给mix test任务来完成此任务?