首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

ExUnit.Case

帮助定义测试用例。

该模块必须在其他模块中用作配置和准备测试的方式。

使用时,它接受以下选项:

  • :async-将此特定测试用例配置为与其他测试用例并行运行。当此测试用例不更改任何全局状态时,可用于性能。默认为false...中定义的所有回调自动包含此模块。ExUnit.Callbacks有关以下内容的更多信息,请参见该模块setup,,,start_supervised,,,on_exit以及测试过程生命周期。有关将测试分组在一起,请参见describe/2在这个模块里。
  • 实例 defmodule AssertionTest do # Use the module use ExUnit.Case, async: true # The "test" macro is imported by ExUnit.Case test "always pass" do assert true end 语境所有测试都接收一个上下文作为参数。上下文对于在回调和测试之间共享信息特别有用:defmodule KVTest do use ExUnit.Case setup do {:ok, pid} = KV.start_link {:ok, pid: pid} end test "stores key-value pairs", context do assert KV.put(context[:pid], :hello, :world) == :ok assert KV.get(context[:pid], :hello) == :world end 由于上下文是一个map,因此可以匹配模式来提取信息:

test "stores key-value pairs", %{pid: pid} do assert KV.put(pid, :hello, :world) == :ok assert KV.get(pid, :hello) == :world end标签上下文用于从回调传递信息到测试。为了将信息从测试传递给回调,ExUnit提供了标记。通过标记测试,可以在上下文中访问标记值,从而允许开发人员自定义测试。让我们看看一个例子:defmodule FileTest do # Changing directory cannot be async use ExUnit.Case, async: false setup context do # Read the :cd tag value if cd = context[:cd] do prev_cd = File.cwd! File.cd!(cd) on_exit fn -> File.cd!(prev_cd) end end :ok end @tag cd: "fixtures" test "reads UTF-8 fixtures" do File.read("hello") end end在上面的例子中,我们已经定义了一个名为:cd的标签,它在setup回调中被读取以配置测试将要运行的工作目录。当使用案例模板(ExUnit.CaseTemplate)时,标记也可以非常有效地允许回调 在案例模板中自定义测试行为。注意标签可以通过两种不同的方式设置:@tag key:value

@tag:key#相当于设置@tag key:true如果给定一个标签不止一次,则最后一个值为wins.Module和describe tagsA可以为模块中的所有测试设置标签或通过设置@moduletag或@describetag 分别为:@moduletag:external如果通过@tag设置了相同的键,则@tag值的优先级更高。Known tags以下标记由ExUnit自动设置,因此是保留的:

  • :case-测试用例模块
  • :file-定义测试的文件
  • :line-确定测试的界限
  • :test-测试名称
  • :async-如果测试用例处于异步模式
  • :type-测试的类型(:test:property等)
  • :registered- 用于ExUnit.Case.register_attribute/3的值
  • :describe-测试属于的描述块

以下标记自定义测试的行为方式:

  • :capture_log - 请参阅下面的“日志捕获”部分
  • :skip-在给定的原因下跳过测试
  • :timeout - 以毫秒为单位自定义测试超时(默认为60000)
  • :report - 在错误报告中包含给定的标签和上下文关键字,请参阅“报告标签”部分

报告标签

ExUnit还允许您的上下文中的标签或任何其他密钥包含在错误报告中,使开发人员可以轻松查看在哪些情况下评估测试。为此,您使用:report标签:

代码语言:javascript
复制
@moduletag report: [:user_id, :server]

现在,当发生错误时,有一个标记部分,其中包含每个报告字段的值:

代码:不合格的“OOPS”堆栈跟踪:

代码语言:javascript
复制
 lib/my_lib/source.exs:148

标签:

代码语言:javascript
复制
 user_id: 1
 server: #PID<0.63.0>

Filters(过滤器)

标记也可以用于标识特定的测试,然后可以使用过滤器包括或排除这些测试。最常见的功能是排除某些特定测试的运行,这可以通过ExUnit.configure/1*

代码语言:javascript
复制
# Exclude all external tests from running
ExUnit.configure(exclude: [external: true])

从今以后,ExUnit将不再运行任何具有external设置为true.这种行为可以通过:include选项,通常通过命令行传递:

代码语言:javascript
复制
mix test --include external:true

运行mix help test以获取更多关于如何通过Mix运行过滤器的信息。

标记和过滤器的另一个用例是排除默认情况下具有特定标记的所有测试,而不管其值如何,并仅包含特定的子集:

代码语言:javascript
复制
ExUnit.configure(exclude: :os, include: [os: :unix])

请记住,默认情况下所有测试都包括在内,因此除非它们首先被排除在外,否则include选项没有效果。

日志捕获

ExUnit可以选择性地禁止打印测试期间生成的日志消息。在运行测试时生成的日志消息将被捕获,并且只有在测试失败时才会打印以帮助进行调试。

您可以选择在单个测试中使用这种行为,方法是将它们标记为:capture_log或为ExUnit配置中的所有测试启用日志捕获:

代码语言:javascript
复制
ExUnit.start(capture_log: true)

这个默认值可以被@tag capture_log: false或者@moduletag capture_log: false覆盖。

setup_all块不属于特定的测试,在它们中生成的日志消息%28或测试之间的日志消息%29永远不会被捕获。如果您也想抑制这些消息,请全局删除控制台后端:

代码语言:javascript
复制
config :logger, backends: []

功能

describe(message, list)

共同描述测试

register_attribute(env,name,opts \ [])

注册ExUnit.Case测试期间使用的新属性

register_test(map, type, name, tags)

注册要作为本例的一部分运行的函数。

测试(消息)

用字符串定义未实现的测试。

test(message,var \ quote()do _ end,contents)

用字符串定义测试

描述(消息,列表)(宏)

一起描述测试。

ExUnit.Callbacks.setup/1可能会被调用,并且它将定义一个安装回调,仅为当前块运行。还将描述名添加为标记,允许开发人员运行特定块的测试。

实例

代码语言:javascript
复制
defmodule StringTest do
  use ExUnit.Case, async: true

  describe "String.capitalize/1" do
    test "first grapheme is in uppercase" do
      assert String.capitalize("hello") == "Hello"
    end

    test "converts remaining graphemes to lowercase" do
      assert String.capitalize("HELLO") == "Hello"
    end
  end
end

当使用Mix时,可以在描述块中运行所有测试,如下所示:

代码语言:javascript
复制
mix test --only describe:"String.capitalize/1"

注描述块不能嵌套。开发人员不应依赖层次结构进行组合,而应构建在命名设置之上。例如:

代码语言:javascript
复制
defmodule UserManagementTest do
  use ExUnit.Case, async: true

  describe "when user is logged in and is an admin" do
    setup [:log_user_in, :set_type_to_admin]

    test ...
  end

  describe "when user is logged in and is a manager" do
    setup [:log_user_in, :set_type_to_manager]

    test ...
  end

  defp log_user_in(context) do
    # ...
  end
end

通过禁止支持命名设置的层次结构,开发人员可以简单地浏览每个描述块,并准确地了解所涉及的设置步骤。

register_attribute(env,name,opts \ [])

期间使用的新属性。ExUnit.Case测试。

属性值将作为键/值对在context.registered.键/值对将在每个键/值对之后清除。ExUnit.Case.test/3类似于@tag...

Module.register_attribute/3用于注册属性,则此函数采用相同的选项。

实例

代码语言:javascript
复制
defmodule MyTest do
  use ExUnit.Case
  ExUnit.Case.register_attribute __ENV__, :foobar

  @foobar hello: "world"
  test "using custom test attribute", context do
    assert context.registered.hello == "world"
  end
end

register_test(map, type, name, tags)

注册一个函数作为这种情况的一部分运行。

这被第三方项目(如QuickCheck)用来实现像property/3这样的宏,但是test却定义了一个属性。有关test/3调用此函数的示例,请参阅实现。

测试类型将被转换为字符串并进行复数显示。您可以使用ExUnit.plural_rule/2设置自定义复数。

test(message) (macro)

用字符串定义未实现的测试。

提供一个方便的宏,允许用字符串定义测试,但尚未实现。由此产生的测试将始终失败并打印“未执行”错误消息。由此产生的测试用例也被标记为:not_implemented

实例

代码语言:javascript
复制
test "this will be a test in future"

test(message,var \ quote()do _ end,contents)(宏)

用字符串定义测试。

提供一个方便的宏,允许使用字符串定义测试。该宏自动插入原子:ok作为测试的最后一行。也就是说,通过测试总是会返回:ok,但更重要的是,它会迫使Elixir不要拖尾调用优化测试,因此避免从回溯中隐藏线。

实例

代码语言:javascript
复制
test "true is equal to true" do
  assert true == true
end

扫码关注腾讯云开发者

领取腾讯云代金券