`
lzs2014193
  • 浏览: 25681 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

erlang开发中使用EUnit进行单元测试

阅读更多

目录:

 

3.1 包含EUnit头文件

3.2 写一个简单的生成函数

3.3 运行EUnit

3.4 写一个测试的生成函数

3.5 一个实例

3.6 关闭测试

3.7 避免编译时期对EUnit的信赖

 

三、开始

 

3.1 包含EUnit头文件

 

在erlang模块中用EUnit最简单的方法是在模块的开头增加如下代码:

 

-include_lib(“eunit/include/eunit.hrl”).

 

增加这个之后会有如下作用:

 

1、自动输出test/0函数(除非你关闭测试,并且你的模块中没有test/0函数),它可以用来运行在本模块所有的单元测试

 

2、所有匹配…_test()或者…_test_()的函数自动输出(除非你关闭测试,或者定义了 EUNIT_NOAUTO宏)

 

3、让EUnit中的所有宏生效来帮助测试

 

注意:要想让-include_lib(…)工作,你的“搜索路径”必须包括eunit/ebin目录。当然如果lib/eunit已经安装在你的系统目录下,它的ebin子目录也就会自动加入到“搜索路径”了,你就不用再做这方面的操作了。否则你就要用erl -pa命令把这个目录加上。当然如果你想在与erlang交互时始终能用EUnit,你只需要这样做:在你的 $HOME/.erlang文件中增加一行:code:add_path(“/path/to/eunit/ebin”).

 

3.2 写一个简单的测试函数

 

用EUnit框架让你在erlang中写一个单元测试非常简单。有好几种方式可以实现。这儿我们先介绍一种最简单的办法:

 

一个以…test()结尾的函数在EUnit中被认为是最简单的函数,它没有参数,它要么执行成功,要么执行失败。执行成功就会返回EUnit抛出的任意值; 执行失败就会抛出一种异常。

 

下面是一种简单的测试函数:

 

reverse_test() -> lists:reverse([1,2,3]).

 

它只是用来测试list:reverse(List)函数不会崩溃。这不是一个好的测试,但很多人写这样简单的函数来测试他们代码的基本功能,而这些测试不用修改就可以直接被EUnit利用,只要是它的函数名匹配(即以_test结尾)。

 

1、用异常来标志出错

 

为写一个比较有趣的测试,我们要让它在得不到我们期待的结果时抛出异常。一种简的方式是用“=”进行模式匹配,如下:

 

reverse_nil_test() -> [] = lists:reverse([]).

reverse_one_test() -> [1] = lists:reverse([1]).

reverse_two_test() -> [2,1] = lists:reverse([1,2]).

 

如上例子可以知道如果得到不是预想的结果就会抛出badmatch异常。注意:Eunit不是智能的,如果你写一个测试只返回一个值,即使它是一个错误的结果,EUnit也只会认为它是成功的。你必须确保你写的测试函数在它得到的结果不是它应该得到的结果时产生崩溃。

 

2、用assert宏

 

用布尔操作来做你的测试,具体查看EUnit 宏

 

例: length_test() -> ?assert(length([1,2,3]) =:= 3).

 

在宏?assert(Expression) 中,它将会计算Expression的值,如果不是true它就会抛出一个异常,否则它就会返回一个ok。在上面的例子中如果 length([1,2,3]的值不是3的话,就会失败。

 

3.3 运行EUnit

 

首先要先按照上面的步骤把声明  -include_lib(“eunit/include/eunit.hrl”)加到你的模块里面, 你只需要编译这个模块,它就会自动输出这个模块的test()函数,而不需要再用-export进行声明,一切都已经自动做好了。

 

这儿你也可以用eunit:test/1函数来运行任意的测试。例如:你用eunit:test(Mod).和用Mod:test().执行的结果是一样的。但eunit:test/1方法可以进行更高级的测试,如:eunit:test({inparallel, Mod}).这个命令和Mod:test()运行的结果是一样的,只不过它是要让它们全部并行的运行。

 

1、把源码和测试代码放在不同的模块里

 

如果你想把你的测试代码和源码分开(当然这儿的测试代码就只能用于测试源码中输出的函数),你可以写一个名为Mod_tests的模块(注意这儿是Mod_tests而不是Mod_test)。这样当您想测试模块Mod时,你就可以运行Mod_tests中的测试函数来实现这个功能了。

 

2、EUnit会捕捉到标准的输出

 

如果你想测试标准的输出函数,你会惊奇的发现在控制台上不会显示出这些文本。因为EUnit捕捉到了所有的标准输出。为了在测试时挠开EUnit好把文本直接打印到控制台,你可以用io:format(user, “~w”, [Term]).把文本打印到输出流user上。这儿推荐的方式是用EUnit的调试宏,它会让这实现的更为简单。

 

3.4 写一个测试的生成函数

 

简单测试函数的缺点是你必须为每个测试实例写一个测试函数。一种更紧凑的方式不是写一个函数来进行测试,而是写一个函数来返回测试结果。

 

一个以…_test_()结尾的函数在EUnit中被认为是一个测试生成函数。测试生成函数返回一系列的测试函数。

 

这儿说下我自己的理解:

 

简单函数只能证明这个函数对应的测试没有问题,如果这个简单函数里面有N条语句进行测试,只有当所有这N条函数都执行成功时才返回成功。而测试生成函数会为每条语句生成一个测试结果,你就可以很方便的知道是哪个函数出现了问题了。

 

1、用数据的方式展现测试

The most basic representation of a test is a single fun-expression that takes no arguments. For example, the following test generator:

 

basic_test_() ->

fun () -> ?assert(1 + 1 =:= 2) end.

 

will have the same effect as the following simple test:

 

simple_test() ->

?assert(1 + 1 =:= 2).

 

(in fact, EUnit will handle all simple tests just like it handles fun-expressions: it will put them in a list, and run them one by one).

 

这儿最后一句提到,它会把每一条语句放到一个列表中,然后一个个的执行它。其实就相当于为每个语句生成一个简单的测试函数。在上面的那两个例子表示效果一样的原因是它们都只有一个函数。

 

2、用宏来写测试

To make tests more compact and readable, as well as automatically add information about the line number in the source code where a test occurred (and reduce the number of characters you have to type), you can use the _test macro (note the initial underscore character), like this:

 

basic_test_() ->

?_test(?assert(1 + 1 =:= 2)).

 

The _test macro takes any expression (the “body”) as argument, and places it within a fun-expression (along with some extra information). The body can be any kind of test expression, just like the body of a simple test function.

 

注:用宏来写的原因主要是为了让代码最紧凑而且减少代码的数量

 

3、用有下划线前缀的宏来创建测试对象

But this example can be made even shorter! Most test macros, such as the family of assert macros, have a corresponding form with an initial underscore character, which automatically adds a ?_test(…) wrapper. The above example can then simply be written:

 

basic_test_() ->

?_assert(1 + 1 =:= 2).

 

which has exactly the same meaning (note the _assert instead of assert). You can think of the initial underscore as signalling test object.

 

注:用_assert宏可以让代码更加紧凑,而且它和前面的简单测试中用到的assert宏用法一样,更加方便。

 

这儿 ?_test(?_assert(1+1 =:= 2)).的功能和?_assert(1+1 =:= 2).是一样的。

 

3.5 一个实例

Sometimes, an example says more than a thousand words. The following small Erlang module shows how EUnit can be used in practice.

-module(fib).

-export([fib/1]).

-include_lib("eunit/include/eunit.hrl").

 

fib(0) -> 1;

fib(1) -> 1;

fib(N) when N > 1 -> fib(N-1) + fib(N-2).

 

fib_test_() ->

[?_assert(fib(0) =:= 1),

?_assert(fib(1) =:= 1),

?_assert(fib(2) =:= 2),

?_assert(fib(3) =:= 3),

?_assert(fib(4) =:= 5),

?_assert(fib(5) =:= 8),

?_assertException(error, function_clause, fib(-1)),

?_assert(fib(31) =:= 2178309)

].

 

(Author’s note: When I first wrote this example, I happened to write a * instead of + in the fib function. Of course, this showed up immediately when I ran the tests.)

3.6 关闭测试

Testing can be turned off by defining the NOTEST macro when compiling, for example as an option to erlc, as in:

 

erlc -DNOTEST my_module.erl

 

or by adding a macro definition to the code, before the EUnit header file is included:

 

-define(NOTEST, 1).//这儿的值不重要,为1或true都没关系!

 

当你想关闭测试时有两种办法:一种是在编译时定义宏NOTEST, 或者在EUnit头文件被包含之前在源文件里增加对宏的声明。

 

(the value is not important, but should typically be 1 or true).

 

Note that unless the EUNIT_NOAUTO macro is defined, disabling testing will also automatically strip all test functions from the code, except for any that are explicitly declared as exported.

For instance, to use EUnit in your application, but with testing turned off by default, put the following lines in a header file:

 

-define(NOTEST, true).

-include_lib(“eunit/include/eunit.hrl”).

 

and then make sure that every module of your application includes that header file. This means that you have a only a single place to modify in order to change the default setting for testing. To override the NOTEST setting without modifying the code, you can define TEST in a compiler option, like this:

 

erlc -DTEST my_module.erl

 

3.7 避免EUnit在编译时期的依赖性

If you are distributing the source code for your application for other people to compile and run, you probably want to ensure that the code compiles even if EUnit is not available. Like the example in the previous section, you can put the following lines in a common header file:

 

-ifdef(TEST).

-include_lib(“eunit/include/eunit.hrl”).

-endif.

 

and, of course, also make sure that you place all test code that uses EUnit macros within -ifdef(TEST) or -ifdef(EUNIT) sections.

分享到:
评论

相关推荐

    erlang eunit

    单元测试是指对软件中的最小可测试单元进行检查和验证,确保每个部分都能按预期工作。EUnit通过定义一组预设的测试函数和宏,允许开发者轻松地编写和运行测试用例,检查函数或模块的行为是否符合预期。 ### 版本与...

    使用rebar工具开发erlang工程项目和发布erlang工程项目借鉴.pdf

    在Erlang开发中,rebar是一个非常重要的工具,它能够帮助开发者编译、测试、打包和管理依赖项。下面将详细介绍rebar在Erlang项目开发中的作用和使用步骤。 1. **准备工作** - 安装Erlang环境:首先,你需要在系统...

    erlang程序设计(第二版)随书源码

    10. **测试和调试**:Erlang提供了`eunit`测试框架和`observer`工具来帮助开发者进行单元测试和系统监控。 通过深入研究《Erlang程序设计(第二版)》的随书源码,你可以逐步掌握这些关键知识点,并提升在实际项目...

    Erlang深度分析

    调试是软件开发中不可或缺的环节,Erlang提供了许多强大的调试工具,例如Erlang的crash dump分析工具、snooper消息监听器等,它们帮助开发者在开发和测试阶段快速定位和解决问题。 #### 4. 并发与网络 ##### 4.1 ...

    erlang实战IP查询服务

    - 使用Erlang自带的测试工具进行单元测试(eunit)和集成测试(common_test)。 5. **部署上线**: - 打包项目为Erlang release版本。 - 部署至生产环境。 #### 六、项目特色 - **高效性**: Erlang语言本身具有高度...

    Erlang-game-server开发实践.zip

    在本文中,我们将深入探讨如何使用Erlang语言进行游戏服务器的开发实践。Erlang是一种功能强大的并行计算和分布式系统编程语言,以其在高并发、容错性和实时性方面的出色性能,被广泛应用于构建大规模、高可用性的...

    erlang+android

    标题 "erlang+android" 暗示了我们将探讨如何在Android开发中使用Erlang这一编程语言。Erlang是一种面向并发、分布式、容错的动态类型语言,以其在实时系统和高并发环境中的优秀表现而知名。在Android平台上使用...

    Erlang中文基礎教程

    Erlang提供了调试工具如observer和tracer,以及单元测试框架如eunit和ct(Common Test),便于进行代码调试和测试。 ### 9. 实战应用 Erlang在实时通信、分布式计算、物联网等领域有着广泛应用,比如著名的开源...

    erlang mochiweb-test demo

    这个 "erlang mochiweb-test demo" 压缩包很可能是为了展示如何使用 Mochiweb 在 Erlang 中构建一个简单的 Web 应用程序或测试环境。 Mochiweb 的核心组件包括以下几个部分: 1. **HTTP 服务器**:Mochiweb 提供了...

    erlang 深度分析

    - **概念**: 使用Erlang开发高性能的网络应用程序。 - **特性**: - **高并发**: 利用轻量级进程模型处理大量并发连接。 - **容错性**: 设计时充分考虑了系统的容错性。 - **应用场景**: 实时通信、在线游戏等领域...

    Erlang实战

    - **单元测试与集成测试**:利用Erlang提供的eUnit和CommonTest框架编写测试用例,确保代码质量。 #### 五、结论 通过本案例的学习,我们不仅了解了如何使用Erlang构建高性能的在线IP查询服务,而且还深入学习了...

    erlang高级原理和应用PPT

    9. **开发工具与实践**:Erlang的开发环境如Eclipse插件(ErlyDTL)、文本编辑器集成、Git版本控制,以及测试框架如eunit和CT(Common Test)。 综上所述,这份PPT将为学习者提供一个深入了解Erlang高级特性和实际...

    erlang_win_64位安装包

    学习Erlang,你需要熟悉其语法、进程通信机制、 OTP(Open Telephony Platform)框架以及相关的开发工具,如Rebar3用于构建和管理项目,Eclipse插件如ErlyDTL用于IDE支持,和EUnit测试框架等。了解这些知识点,你就...

    erlang open poker 最好的入门程序源码

    9. **测试驱动开发**:Erlang社区非常重视测试,源码可能包含EUnit或PropEr等测试框架的用例,展示如何为Erlang代码编写测试。 通过深入研究这个开源项目,你不仅可以掌握Erlang语言的基本用法,还能理解并发和...

    erlang-formula

    二郎 二郎 安装erlang语言 ... 安装erlang单元测试框架 erlang.manpages 安装 erlang 联机帮助页。 erlang.nox 安装不需要 X Window 系统的 erlang 应用程序。 erlang.hipe 安装 erlang HiPe 应用程序

    meck:Erlang的模拟库

    在Erlang项目中,通常将meck与EUnit或PropEr等测试框架结合使用,创建全面的测试套件。通过meck,可以有效地测试复杂系统中的单个组件,而无需担心它们的依赖关系。 总的来说,meck为Erlang开发者提供了一种强大的...

    rebar生成erlang release 并进行热代码升级

    这里使用eunit进行简单的测试。 首先,在`src/myapp_app.erl`文件中加入测试相关的代码: ```erlang -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -endif. -ifdef(TEST). simple_test() -> ok = ...

    yamerl:纯Erlang中的YAML 1.2和JSON解析器

    由于Erlang和Elixir之间的紧密联系,yamerl也可以方便地在Elixir项目中使用。通过添加Erlang库依赖,可以轻松调用yamerl的功能: ```elixir def deps do [ {:yamerl, "~> x.x.x", only: :prod, hex: :yamerl} ] ...

Global site tag (gtag.js) - Google Analytics