使用%UnitTest进行单元测试
本教程的第二部分介绍了如何使用%UnitTest包对InterSystems IRIS代码进行单元测试。完成本教程的这一部分后,将能够:
- 解释
%UnitTest
包中三个主要类的角色。 - 列出基于
%UnitTest
包的单元测试类和方法的要求。 - 创建并执行方法的单元测试。
- 浏览
%UnitTest.Manager
创建的测试报告。 - 执行单元测试时,使用
%UnitTest.TestCase
方法初始化和还原数据库数据。
什么是%UnitTest?
%UnitTest
包是一组为IRIS提供测试框架的类。在结构上,它类似于xUnit
测试框架。%UnitTest
为创建和执行以下各项的单元测试提供类和工具:
- 类和方法
- ObjectScript例程(routines)
- InterSystems SQL脚本
- Productions
创建和执行单元测试套件
以下是创建和执行一套单元测试的基本步骤:
- 创建一个(或多个)包含要测试的方法的类。
- 创建扩展
%UnitTest.TestCase
的测试类(或多个测试类)。 - 将方法添加到将测试方法输出的测试类。在每个方法中至少使用一个断言(
AssertX
宏)。每个测试方法名称都以Test
开头。 - 将测试类导出到文件。
- 打开终端并切换到包含要测试的类的名称空间。为
^UnitTestRoot
分配一个字符串,该字符串包含包含导出的测试类文件的目录的父目录的路径。 - 在终端中,运行
%UnitTest.Manager.RunTest
,向其传递包含测试类文件的(子)目录的名称。 - 查看测试报告。终端中的输出包括网页的URL,该网页以易于阅读的表格形式显示结果。
%UnitTest类
此表描述了用于为InterSystems IRIS类和方法创建和执行单元测试的主要%UnitTest
类。
-
TestCase
扩展此类以创建包含测试方法的类。如果一个或多个AssertX
方法返回False
,则测试失败;否则测试通过。将使用关联的宏调用AssertX
方法。这些方法和宏是:-
AssertEqualsViaMacro
-如果表达式相等,则返回TRUE
。使用$$$AssertEquals
宏调用。 -
AssertNotEqualsViaMacro
-如果表达式不相等,则返回TRUE
。使用$$$AssertNotEquals
宏调用。 -
AssertStatusOKViaMacro
-如果返回的状态代码为1,则返回TRUE
。使用$$$AssertStatusOK
宏调用。 -
AssertStatusNotOKViaMacro
-如果返回的状态码为0,则返回TRUE
。使用$$$AssertStatusNotOK
宏调用。 -
AssertTrueViaMacro
-如果表达式为TRUE,则返回TRUE。使用$$$AssertTrue
宏调用。 -
AssertNotTrueViaMacro
-如果表达式不为TRUE,则返回TRUE
。使用$$$AssertNotTrue
宏调用。 -
AssertFilesSameViaMacro
-如果两个文件相同,则返回TRUE
。使用$$$AssertFilesSame
宏调用。 -
LogMessage
-将日志消息写入^UnitTestLog
全局。使用$$$LogMessage
宏调用。 - 设置和拆除条件的方法包括:
-
OnBeforeOneTest
-紧接在测试类中的每个测试方法之前执行。 -
OnBeforeAllTests
-在测试类中的任何测试方法之前执行一次。 -
OnAfterOneTest
-在测试类中的每个测试方法之后立即执行。 -
OnAfterAllTests
-在测试类中的所有测试方法执行完毕后执行一次。
-
-
Manager
使用此类启动测试。其方法包括:-
RunTest
-在目录中执行一个测试或一组测试。 -
DebugRunTestCase
-执行一个测试或一组测试,而不加载或删除任何测试类。
-
-
Report
定义报告执行一个测试或一组测试的结果的网页。
断言方法和宏
单元测试的主要测试操作来自AssertX
方法及其关联宏。将直接调用宏来测试方法的输出。宏测试方法是否为给定的输入创建所需的输出。只要AssertX
宏返回FALSE
(或以错误结束),包含它的测试就会失败。
在创建代码时,请计划将创建的单元测试以测试代码。在这里的示例中,已经创建了一个名为TestMe
的类,其中包含一个名为Add
的方法。现在想测试一下新的TestMe
类,看看它是否工作。
以下命令运行AssertEquals
宏以测试Add
方法的输入(2,2)
是否等于4
。
Do $$$AssertEquals(##class(MyPackage.TestMe).Add(2,2),4, "Test Add(2,2)=4")
AssertEquals
宏比较两个值并接受三个参数:
-
##class(MyPackage.TestMe).Add(2,2)
-第一个值是以2,2
作为输入进行测试的方法。 -
4
-第二个值。 -
"Test Add(2,2)=4"
-写在结果页上的文本说明。(此参数不影响测试。如果不包含测试描述,该类将使用求值的表达式创建一个测试描述。)
以下是用于测试对象是否正确保存的AssertStatusOK
宏的示例。
Do $$$AssertStatusOK(contact.%Save(),"Saving a Contact")
此AssertStatusOk
宏计算方法返回的状态。如果为1,则测试通过。
-
Contact.%Save
-返回状态代码的表达式。 -
"Saving a Contact"
-文本说明。这是测试报告的文档。这不会影响测试。
创建要在示例中使用的类
要完成以下动手示例,请使用Atelier
创建以下类:MyPackage.TestMe
和MyPackage.Contact
。
MyPackage.TestMe
Class MyPackage.TestMe Extends %RegisteredObject
{
ClassMethod Add(arg1 As %Integer, arg2 As %Integer) As %Integer
{
Return arg1 arg2
}
ClassMethod CreateContact(name As %String, type As %String) As MyPackage.Contact
{
Set contact = ##class(MyPackage.Contact).%New()
Set contact.Name=name
Set contact.ContactType=type
Return contact
}
ClassMethod GetContactsByType(type As %String) As %ListOfObjects
{
Set list=##class(%Library.ResultSet).%New()
}
}
MyPackage.Contact
Class MyPackage.Contact Extends (%Persistent, %Populate, %XML.Adaptor)
{
/// 描述联系的性质:: Personal or Business
Property ContactType As %String(TRUNCATE = 1, VALUELIST = ",Business,Personal");
/// 表示联系人的姓名
Property Name As %String(POPSPEC = "Name()", TRUNCATE = 1) [ Required ];
Query ByContactType(type As %String) As %SQLQuery(CONTAINID = 1)
{
SELECT %ID FROM Contact
WHERE (ContactType = :type)
ORDER BY Name
}
Storage Default
{
<Data name="ContactDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>ContactType</Value>
</Value>
<Value name="3">
<Value>Name</Value>
</Value>
</Data>
<DataLocation>^MyPackage.ContactD</DataLocation>
<DefaultData>ContactDefaultData</DefaultData>
<IdLocation>^MyPackage.ContactD</IdLocation>
<IndexLocation>^MyPackage.ContactI</IndexLocation>
<StreamLocation>^MyPackage.ContactS</StreamLocation>
<Type>%Storage.Persistent</Type>
}
}
示例:创建并导出测试类
类MyPackage.TestMe
包含一个名为Add
的方法,该方法将两个整数相加。在此示例中,将创建并运行单元测试以检查Add
方法是否正确地将两个整数相加。
创建将包含单元测试的测试类。以下是方法:
- 使用Atelier在
MyPackage
包中创建名为Tests
的新类。测试必须扩展%UnitTest.TestCase
。 - 添加以下名为
TestAdd
并编译测试的方法:
Class MyPackage.Tests Extends %UnitTest.TestCase
{
Method TestAdd()
{
do $$$AssertEquals(##class(MyPackage.TestMe).Add(2,2),4, "Test Add(2,2)=4")
do $$$AssertNotEquals(##class(MyPackage.TestMe).Add(2,2),5,"Test Add(2,2)'=5")
}
}
- 将类测试导出到单元测试目录中的XML文件。如果尚未创建测试目录,请创建一个。此示例使用 `C:unittestsmytests。
a. 在Atelier中,单击文件>导出。
b. 在“Atelier ”下,单击“旧版XML文件”。单击下一步
c. 选择项目Test.cls
和c:unittestsmytests
目录。
d. 单击Finish(完成)。
e. Atelier将测试类导出到C:unittestsmytestsclsMyPackage
。
注意,目录名(在本例中为mytest
)是一套测试的名称,也是^UnitTestRoot
指定的目录的子级。运行Manager.RunTest(“mytest”)
运行存储在mytest
目录中的所有测试。
注意:还可以将测试类导出为.cls
文件,而不是XML
文件。也可以简单地从Atelier工作区复制它们,而不是导出它们。