zoukankan      html  css  js  c++  java
  • Elixir 单元测试

    概述

    elixir 中自带了单元测试框架 ExUnit ,其中提供单元测试的一系列,主要包含以下模块:

    1. ExUnit: 单元测试框架
    2. ExUnit.Assertions: 断言
    3. ExUnit.Case: 测试用例
    4. ExUnit.DocTest: 在注释写测试用例,类似 python 的 doctest
    5. ExUnit.Callbacks: 单元测试中回调
    6. ExUnit.CaseTemplate: 测试用例模板,用在有大量同类测试的场景
    7. ExUnit.Test: 单元测试信息,用于描述单元测试本身,相当于单元测试的元数据
    8. ExUnit.TestCase: 测试用例信息,用于描述单元测试用例本身,相当于测试用例的元数据
    9. ExUnit.CaptureIO 和 ExUnit.CaptureLog: 辅助测试时获取 IO 和 log 的输出
    10. ExUnit.Formatter: 格式化测试输出的信息
    11. ExUnit.Filters: 控制测试用例的过滤

    一般主要使用的模块是 ExUnit.Assertions,ExUnit.Case,ExUnit.DocTest

    单元测试

    下面通过各种测试用例的场景,来实际应用上面提到的各个模块。

    构造一个测试场景

    为了简单,假定测试的对象是一个计算器,包含基本的加减乘除运算。 创建工程,然后添加 加减乘除 四个方法:

    $ mix new calc
    * creating README.md
    * creating .gitignore
    * creating mix.exs
    * creating config
    * creating config/config.exs
    * creating lib
    * creating lib/calc.ex
    * creating test
    * creating test/test_helper.exs
    * creating test/calc_test.exs
    
    Your Mix project was created successfully.
    You can use "mix" to compile it, test it, and more:
    
        cd calc
        mix test
    
    Run "mix help" for more commands.
    

    工程自动生成的代码 lib/calc.ex 中带有一个示例函数 hello

    defmodule Calc do
      @moduledoc """
      Documentation for Calc.
      """
    
      @doc """
      Hello world.
    
      ## Examples
    
          iex> Calc.hello
          :world
    
      """
      def hello do
        :world
      end
    end
    

    上面的 ##Examples 下的就是 doctest

    然后,在上面的 Calc module 中增加4个简单的带测试函数:

    def add(x, y) do
      x+y
    end
    
    def minus(x, y) do
      x-y
    end
    
    def mul(x, y) do
      x*y
    end
    
    def division(x, y) do
      div x, y
    end
    

    添加测试case (test/calc_test.exs)

    针对上面4个方法,各写几个测试 case 如下:

    defmodule CalcTest do
      use ExUnit.Case
    
      test "add method test" do
        assert Calc.add(3, 3) == 6
      end
    
      test "add method test 2" do
        refute Calc.add(3, 3) == 5
      end
    
      test "minus method test" do
        assert Calc.minus(3, 3) == 0
      end
    
      test "multiply method test" do
        assert Calc.mul(3, 3) == 9
      end
    
      test "division method test" do
        assert Calc.division(3, 3) == 1
      end
    end
    

    其中,test 方法来自于模块 ExUnit.Case, assert,refute 等来自于 ExUnit.Assertions 模块。 其他 assertion 参考: https://hexdocs.pm/ex_unit/ExUnit.Assertions.html

    设置统一的测试参数

    上面的测试是最基本的示例,上面的测试用例中每个用例的参数都是 (3,3),可以用 setup 方法统一设置每个case的相同参数。

    defmodule CalcTest do
      use ExUnit.Case, async: true
    
      setup do
        {:ok, [x: 3, y: 3]}
      end
    
      test "add method test", context do
        assert Calc.add(context[:x], context[:y]) == 6
      end
    
      test "add method test 2", context do
        refute Calc.add(context[:x], context[:y]) == 5
      end
    
      test "minus method test", context do
        assert Calc.minus(context[:x], context[:y]) == 0
      end
    
      test "multiply method test", context do
        assert Calc.mul(context[:x], context[:y]) == 9
      end
    
      test "division method test", context do
        assert Calc.division(context[:x], context[:y]) == 1
      end
    end
    

    除了 setup,还有 setup_all 方法也可以设置每个 case 的共通参数。 不同之处在于 setup 每个 test 执行之前都会运行。

    测试中的回调

    测试回调除了上面的 setup 和 setup_all 之外,还有一个 on_exit 回调,在每次测试case执行完之后运行。 以上回调属于 ExUnit.Callbacks 模块。

    上面的setup中加入 on_exit 的回调:

    setup context do
      on_exit fn ->
        IO.puts "#{context[:test]} finished!"
      end
    
      {:ok, [x: 3, y: 3]}
    end
    

    context[:test] 中是每个 test 后跟的字符串。 修改后执行结果如下:

    $ mix test
    test multiply method test finished!
    .test add method test 2 finished!
    .test add method test finished!
    .test division method test finished!
    .test minus method test finished!
    .
    
    Finished in 0.04 seconds
    5 tests, 0 failures
    
    Randomized with seed 604679
    

    总结

    elixir 中自带了完善的单元测试库,但是没有 mock 库,因为 elixir 社区不推荐使用 mock, 社区认为如果代码遵循良好的设计规范,就会很容易测试。

    此外,ExUnit 中的还有些模块没有尝试,以后在实际用到时再写相应的心得。

  • 相关阅读:
    类的继承
    面向对象的编程
    Python的模块
    ES6_12_Set和Map数据结构以及for of循环
    ES6_11_字符串、数值、数组、对象扩展
    ES6_09_Generator函数
    ES6_08_Iterator遍历器
    ES6_07_Symbol属性
    ES6_05_三点运算符和形参默认值
    Sqlstate解释
  • 原文地址:https://www.cnblogs.com/wang_yb/p/6357545.html
Copyright © 2011-2022 走看看