13. 测试
13.1. 测试
测试是Tigase服务器开发过程中非常重要的一部分。
每个版本都经过完全自动化的测试过程。所有服务器功能仅在通过测试周期时才被视为已实现。 Tigase测试套件用于我们所有的自动测试,允许定义不同的测试场景。
没有调整用于测试的数据库。所有数据库都以标准方式安装并使用默认设置运行。每次测试周期开始前都会清除数据库。
也不需要对Tigase的配置文件进行修改。所有测试均在配置向导生成的默认配置上执行。
该服务器在所有支持的环境中进行了测试:
XMLDB - 使用内置的简单XML数据库进行测试。对于小型安装,这是一种简单而有效的解决方案。尽管它已经成功测试了 10,000 个用户帐户,但建议用于具有多达100个用户帐户的服务。
MySQL - 使用 MySQL 数据库进行测试。比 XMLDB 慢得多,但可以处理更多的用户帐户。
PostgreSQL - 使用 PostgreSQL 数据库进行测试。同样,它比XMLDB慢得多,但可以处理更多的用户帐户。这与MySQL数据库(SQL连接器)的代码基本完全相同,但会执行测试以确保代码与所有支持的SQL数据库兼容并比较性能。
Distributed - 是分布式安装的测试,其中c2s和s2s组件在分离的机器上运行,该机器使用外部组件协议 (XEP-0114) 连接到另一台运行SessionManager的机器。
13.1.1. 功能测试
基本检查以查看所有功能是否正常工作。每次将代码发送到源存储库时都会执行这些测试。
版本 |
XMLDB |
MySQL |
PGSQL |
发布 |
3.3.2-b889 |
无 |
|||
3.3.2-b880 |
无 |
|||
3.0.2-b700 |
||||
2.9.5-b606 |
||||
2.9.3-b548 |
||||
2.9.1-b528 |
||||
2.8.6-b434 |
||||
2.8.5-b422 |
||||
2.8.3-b409 |
||||
2.7.2-b378 |
||||
2.6.4-b300 |
||||
2.6.4-b295 |
||||
2.6.0-b287 |
||||
2.5.0-b279 |
||||
2.4.0-b263 |
||||
2.3.4-b226 |
无 |
无 |
无 |
13.1.2. 性能测试
检查函数是否执行得足够好。
版本 |
XMLDB |
MySQL |
PGSQL |
发布 |
3.3.2-b889 |
无 |
|||
3.3.2-b880 |
无 |
|||
3.0.2-b700 |
||||
2.9.5-b606 |
||||
2.9.3-b548 |
||||
2.9.1-b528 |
||||
2.8.6-b434 |
||||
2.8.5-b422 |
||||
2.8.3-b409 |
||||
2.7.2-b378 |
||||
2.6.4-b300 |
||||
2.6.4-b295 |
||||
2.6.0-b287 |
||||
2.5.0-b279 |
||||
2.4.0-b263 |
||||
2.3.4-b226 |
无 |
无 |
无 |
13.1.3. 稳定性测试
检查该功能在长期运行中是否表现良好。它必须在几个小时的服务器运行中每秒处理数百个请求。
版本 |
XMLDB |
MySQL |
PGSQL |
发布 |
2.3.4-b226 |
无 |
无 |
无 |
13.2. Tigase测试套件
Tigase Test Suite是一个允许您运行测试的引擎。本质上它只是执行 TestCase 实现。测试可能依赖于其他测试,这意味着它们按特定顺序执行。例如,身份验证测试在流打开测试之后执行,而流打开测试又在网络套接字连接测试之后执行。
每个 TestCase 实现都可能有自己的一组特定参数。有一组通用参数可以应用于任何 TestCase。作为通用参数的示例,您可以使用 -loop = 10 指定 TestCase 必须执行10次。测试特定参数可能是 -user-name = tester ,它可以设置身份验证测试的用户名。
该引擎非常通用,允许您编写任何类型的测试,但对于Tigase项目,当前的TestCase实现模仿XMPP客户端,旨在测试XMPP 服务器。
该套件包含一种脚本语言,允许您将测试用例组合到测试场景中。测试场景可能包含全套功能测试,比如,另一个测试场景可能包含性能测试等。
13.2.1. 运行Tigase测试套件 (TTS)
要获取TTS,您首先需要克隆存储库
git clone https://repository.tigase.org/git/tigase-testsuite.git
克隆完成后,导航到TTS根目录并使用maven编译:
mvn clean install
Maven将编译TTS并将jars放在必要的位置。在同一目录中,您可以使用以下命令开始运行TTS:
./scripts/all-tests-runner.sh
您应该看到以下内容,其中概述了自定义测试运行的可能选项
Run selected or all tests for Tigase server
----
Author: Artur Hefczyc <[email protected]>
Version: 2.0.0
----
--help|-h This help message
--func [mysql|pgsql|derby|mssql|mongodb]
Run all functional tests for a single database configuration
--lmem [mysql|pgsql|derby|mssql|mongodb]
Run low memory tests for a single database configuration
--perf [mysql|pgsql|derby|mssql|mongodb]
Run all performance tests for a single database configuration
--stab [mysql|pgsql|derby|mssql|mongodb]
Run all stability tests for a single database
configuration
--func-all Run all functional tests for all database
configurations
--lmem-all Run low memory tests for all database
configurations
--perf-all Run all performance tests for all database
configurations
--stab-all Run all stability tests for all database
configurations
--all-tests Run all functionality and performance tests for
database configurations
--single test_file.cot
--other script_file.xmpt
----
Special parameters only at the beginning of the parameters list
--debug|-d Turns on debug mode
--skip-db-relad|-no-db Turns off reloading database
--skip-server|-no-serv Turns off Tigase server start
--small-mem|-sm Run in small memory mode
-----------
Other possible parameters are in following order:
[server-dir] [server-ip]
13.2.2. 自定义Tigase测试套件
您可以像上面一样从命令行运行测试,但是您可以创建和编辑 /scripts/tests-runner-settings.sh 文件以适应您的Tigase安装,并避免像此模板所示的那样使用冗长的复杂命令:
#!/bin/bash
func_rep="func-rep.html"
perf_rep="perf-rep.html"
db_name="tigasetest"
db_user="tigase"
db_pass="tigase"
root_user="root"
root_pass="root"
TESTS=("derby" "mysql" "pgsql" "mssql")
IPS=("127.0.0.1" "127.0.0.1" "127.0.0.1" "127.0.0.1")
server_timeout=10
server_dir="/home/tigase/tigase-server"
database="derby"
#database="mysql"
server_ip="127.0.0.1"
MS_MEM=100
MX_MEM=1000
SMALL_MS_MEM=10
SMALL_MX_MEM=50
这将允许您通过多次运行TTS来保持相同的设置。请参阅下一节以了解脚本语言的工作原理以及如何创建和运行自己的自定义测试。
13.3. 测试套件脚本语言
测试套件包含脚本语言,允许您将测试用例组合到测试场景中。然而,在最低级别上,该语言旨在允许您通过设置测试参数、测试注释、标识等来描述测试。
让我们看一下示例测试描述。
Short name@test-id-1;test-id-2: Short description for the test case
{
-loop = 10
-user-name = Frank
# This is a comment which is ignored
}
>> Long, detailed description of the test case <<
所有元素的含义:
Short name 是您想要的任何描述性名称。它不需要是唯一的,只是告诉你这个测试是关于什么的。@ 是短名称和测试ID之间的分隔符。
test-id-1;test-id-2 是用分号分隔的测试用例ID。测试用例按列出的顺序执行。并在那里列出它们其意味着test-id-2取决于 test-id-1。通常,您不必列出所有依赖项,因为所有强制依赖项都会自动包含在内。这意味着如果您有一个身份验证测试用例,该套件会自动添加网络套接字连接和流打开测试。但是,有时存在可选的依赖项或多个强制依赖项,您需要选择必须执行的依赖项。一个很好的例子是身份验证测试用例。有许多身份验证测试:PLAIN-AUTH、SASL-DIGESTMD5、SASL-PLAIN、DIGEST-AUTH,它们对于大多数其他测试(如 roster、presence 等)都是强制性的。其中一项身份验证测试是默认依赖项,但如果您将不同的身份验证放在列表中,它将被使用而不是默认的。
: 是测试用例ID列表和简短测试描述之间的分隔符。
Short test description 放在: - 冒号和开头 { - 大括号之间。这通常是非常简短的单行测试描述。
{ } 大括号包含所有测试参数,例如必须执行多少次测试或在单独的线程中运行测试、用户名、网络连接的主机IP地址等等。
>> << 在两个大于号和两个小于号里面你放了一个很长的多行测试描述。
对于左大括号 { 和右大括号 } 之间的测试脚本,您可以放置您想要的所有测试用例参数。它的格式是:
-parameter-name = value
参数名称始终以 - 开头。请注意,某些参数不需要任何值。它们可以独立存在而无需分配任何值:
-debug-on-error
这模拟了您是否将 yes 或 true 作为值。
脚本语言还包括对可以分配任何值并在以后多次使用的变量的支持。将值分配给变量的方式与将其分配给参数的方式相同:
$(variable-name) = value
变量名必须始终用方括号 () 括起来并以 $ 开头。
该值可以用双引号 “” 括起来,或者可以省略双引号。如果这是一个简单的字符串,例如仅由数字、字母、下划线 _ 和连字符 - 组成的数字或字符串,则可以省略双引号,否则必须将值括起来。
测试用例描述可以嵌套在其他测试用例描述中。嵌套测试用例描述从外部测试用例描述继承参数和变量。
13.4. 为插件编写测试
您可以在测试套件运行时加载的简单文本文件中编写测试。
您只需指定应发送到服务器哪些内容以及应从服务器获得哪些响应。无需为新测试编写Java代码和重新编译整个测试套件。这意味着现在可以轻松快速地编写新的测试用例,这可能意味着对服务器进行更详细的测试。
这个是如何工作的:
让我们以 XEP-0049 私有XML存储为例。查看规范,我们可以看到第一个示例:
13.4.1. 示例:客户端存储私有数据
客户:
<iq type="set" id="1001">
<query xmlns="jabber:iq:private">
<exodus xmlns="exodus:prefs">
<defaultnick>Hamlet</defaultnick>
</exodus>
</query>
</iq>
服务器:
<iq type="result" id="1001"/>
这对于第一个简单的测试来说已经足够了。我必须创建如下所示的文本文件 JabberIqPrivate.test
:
send: {
<iq type="set" id="1001">
<query xmlns="jabber:iq:private">
<exodus xmlns="exodus:prefs">
<defaultnick>Hamlet</defaultnick>
</exodus>
</query>
</iq>
}
expect: {
<iq type="result" id="1001"/>
}
现在我可以执行测试了:
testsuite $ ./scripts/all-tests-runner.sh --single JabberIqPrivate.test
Tigase server home directory: ../server
Version: 2.8.5-b422
Database: xmldb
Server IP: 127.0.0.1
Extra parameters: JabberIqPrivate.test
Starting Tigase:
Tigase running pid=6751
Running: 2.8.5-b422-xmldb test, IP 127.0.0.1...
Script name: scripts/single-xmpp-test.xmpt
Common test: Common test ... failure!
FAILURE, (Received result doesnt match expected result.,
Expected one of: [<iq id="1001" type="result"/>],
received:
[<iq id="1001" type="error">
<query xmlns="jabber:iq:private">
<exodus xmlns="exodus:prefs">
<defaultnick>Hamlet</defaultnick>
</exodus>
</query>
<error type="cancel">
<feature-not-implemented xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
<text xml:lang="en" xmlns="urn:ietf:params:xml:ns:xmpp-stanzas">
Feature not supported yet.</text>
</error>
</iq>]),
Total: 100ms
Test time: 00:00:02
Shutting down Tigase: 6751
如果我刚开始研究这个XEP并且在服务器端没有代码,那么结果是完全可以预期的,尽管这可能不是我们想要的。在处理服务器代码一段时间后,我可以再次执行测试:
testsuite $ ./scripts/all-tests-runner.sh --single JabberIqPrivate.test
Tigase server home directory: ../server
Version: 2.8.5-b422
Database: xmldb
Server IP: 127.0.0.1
Extra parameters: JabberIqPrivate.test
Starting Tigase:
Tigase running pid=6984
Running: 2.8.5-b422-xmldb test, IP 127.0.0.1...
Script name: scripts/single-xmpp-test.xmpt
Common test: Common test ... success, Total: 40ms
Test time: 00:00:01
Shutting down Tigase: 6984
就是这些。以简单有效的方式获得我们想要的结果。我们可以重复多次,这在长期试验中尤为重要。每次我们更改服务器代码时,我们都可以重新运行测试以确保我们从服务器获得正确的响应。
您可以查看当前构建,包含更完整的测试用例,文件为 JabberIqPrivate。
现在我的服务器测试不再过时。当然,并非所有情况都如此简单。一些XEP要求在发送节之前进行计算或比较接收到的结果。这种情况的一个很好的例子是像SASL甚至NON-SASL这样的用户身份验证。但是,仍然有很多情况可以通过简单的测试来涵盖:名册管理、隐私列表管理、vCard、私人数据存储等等。
13.5. 测试用例参数说明
有一长串参数可以应用于任何测试用例。以下是可用于构建测试场景的所有可能参数的描述。
有一长串参数可以应用于任何测试用例。以下是可用于构建测试场景的所有可能参数的描述。
13.5.1. 测试报告配置
为了从测试中生成HTML报告,必须在主脚本文件中设置测试报告参数。这些参数没有任何影响,因为它们是在测试用例描述中设置的。
-version = 2.0.0 设置测试脚本版本。当测试套件加载为该套件的更新版本创建的脚本并且可能无法在此版本中正常工作时,这用于轻松检测不兼容问题。
-output-format = (html | html-content) 设置测试报告的输出格式。现在实际上只有一种可能的格式 - HTML。这两个选项之间的唯一区别是 html 格式创建带有HTML标题和正文的完整HTML页面。另一方面,html-content 格式只创建
<body/>
元素内的内容。并用于将测试结果嵌入到其他HTML内容中。-output-file = “report-file.html” 设置测试报告的文件名。
-output-history = (yes | no)* 设置测试套件和XMPP服务器之间发送的所有协议数据的日志记录。通常,对于功能测试,建议将其设置为 yes,但对于所有其他测试,如性能或负载测试,应将其设置为 no。
-history-format = separate-file 将协议数据记录设置为单独的文件。目前这是唯一可能的选择。
-output-cols = (5 | 7) 仅有有效值是:
5: "Test name", "Result", "Test time", "Description" [, "History" ] 7: "Test name", "Result", "Total time", "OK", "Average", "Description" [, "History" ]
-title = “报告页的标题” 此参数设置测试报告的标题,它位于HTML页面的 <title/> 元素以及第一页标题中。
13.5.2. 基本测试参数
这些参数可以在每个测试用例的基础上设置,但通常它们在主脚本文件中设置以将它们应用于所有测试用例。
-base-ns = “jabber:client” 设置用于XMPP连接中XML流的XML名称空间。一些测试用例可用于测试客户端到服务器协议以及服务器到服务器协议以及将来可能添加的不同协议。
-debug 打开调试模式。测试套件和服务器之间的所有通信都打印到文本控制台,并且还显示所有其他调试信息,包括 java异常。当某些测试失败并且您想找出原因时,它特别有用。
-debug-on-error 在错误检测时打开调试模式。通常调试输出会生成大量消息,这使得输出很难阅读。特别是在性能测试中,您不仅可以读取协议数据的快速滚动行,而且还会减慢测试速度。但是,如果一切正常,此选项将关闭调试,然后如果我们检测到任何测试错误,则生成调试输出。
-def-auth = (auth-plain | auth-digest | auth-sasl) 设置用户连接的默认身份验证方法。
-def-stream = (stream-client | stream-server | stream-component | stream-bosh) 设置要测试的连接流和连接的命名空间。
-host = “host.name” 测试服务器运行的虚拟主机名。它可能是真实的DNS名称,或者只是为了测试目的而配置的主机名。但是它必须与服务器配置相匹配。
-keys-file = “certs/keystore” 设置密钥存储文件的位置。没必要碰它。
-keys-file-password = keystore 设置密钥库文件的密码。通常你不必触摸它。
-serverip = “127.0.0.1” 定义XMPP服务器IP地址。您可以省略此参数,然后将根据服务器DNS地址自动确定I 地址。但是,如果无法正确解析DNS地址,或者如果您在localhost上运行测试,则可以使用此参数来强制执行IP地址。
-socket-wait = 10000 以毫秒为单位设置网络套接字超时,这是测试套件等待服务器响应的最长时间。您可能希望增加某些特定测试的超时时间,这些测试需要在服务器上进行大量计算或数据库活动。对于大多数情况,通常10秒就足够了。
-stop-on-fail = true 导致脚本终止对第一个失败的测试用例的所有操作。它有助于在故障点诊断服务器状态。
-trust-file = “certs/client_truststore” 设置客户端信任存储文件的文件名。无需更改它。
-trust-file-password = truststore 设置信任库文件的密码。通常你不必触摸它。
-user-name = tester 设置用于测试套件和XMPP服务器之间的XMPP连接的用户名。它通常对所有测试全局设置相同,对于某些测试,如接收服务器配置,您可能希望使用不同的帐户(具有管理员权限)。然后,您可以为这个特定的测试用例设置不同的用户。
-user-pass = tester-password 为用于测试套件和XMPP服务器之间的XMPP连接的用户设置密码。
-user-resr = resource 为测试套件和XMPP服务器之间的XMPP连接设置用户JID资源部分。
13.5.3. 测试用例参数
测试参数通常在每个测试用例的基础上设置,并且仅适用于为其设置的测试和所有继承的测试。不过,有些参数仅适用于继承的测试用例。请查看下面的描述以找到更多详细信息。
-active-connection 是与 -on-one-socket 选项类似的参数。如果设置套件不会关闭网络套接字,并且如果测试在循环中运行,则每个循环运行都会重新使用网络连接。与 -on-one-socket 模式不同,整个测试在每次运行时执行,包括XMPP流初始化和用户身份验证。目前不建议在正常使用中使用此选项。仅在非常特殊的用例中调试服务器行为才有用。
-background 在后台的单独线程中执行测试,并立即将控制权返回给测试套件程序,而无需等待测试完成。默认行为是按顺序执行所有测试,并在前一个测试完成后运行下一个测试。但是,此参数允许同时运行测试。这有点类似于 -daemon 参数的选项。然而,守护程序测试/任务被完全忽略,并且在后台测试是与另一个或可能许多其他测试同时运行的正常测试的情况下,不会收集来自守护程序的结果。
-daemon 在单独的线程中创建在后台运行的任务。这样的测试作为守护进程无限运行,它不记录在测试报告中,也不计算它的结果。此类测试/任务的目的是充当其他测试用例的助手。此类守护程序测试的一个很好的例子是消息响应者 - 以不同的用户名运行并等待消息并响应发送者的测试。
-delay = 1000 设置测试用例完成后的等待时间(毫秒)。如果您想在循环中运行的每个测试用例之间引入短暂的延迟,或者如果您启动助手守护线程并且您必须添加延迟以确保它在下一个真实测试开始发送请求之前准备好工作,您可以使用它守护进程。
-expect-type = error 设置预期作为响应的数据包的类型。某些测试用例(例如消息发送者)有时会期望以与发送数据包(chat)相同的类型进行响应,但在某些其他情况下,当它向已设置隐私列表以阻止消息的用户发送消息时,响应应该会有错误。这样我们就可以使用相同的测试用例来测试不同的响应场景。
-loop = 10 设置测试(以及所有继承的测试)重复的次数。您可以使用 $(loop) 伪变量来获取和使用当前循环运行次数。如果您想为不同的用户名(例如注册10个不同的用户帐户)运行每个循环运行,这很有用。为此,您将$(loop)变量粘贴到用户名字符串:-user-name = “nick_name_$(loop)”。
-loop-delay = 10 为多次运行的测试设置每个单独循环运行之间的延迟(以毫秒为单位)。这与 -delay 参数类似,但 -delay 选项会在整个测试(或所有循环运行)完成后引入延迟。循环延迟选项增加了每次循环测试运行之间的等待时间。
-loop-start = 5 设置循环起始值。它不会以任何方式影响循环运行的次数。它只影响 $(loop) 变量的值。假设您想为具有100k并发用户的服务器运行负载测试,并且您想从3台不同的机器上运行测试。为确保每台机器使用不同的用户帐户,您必须在每台机器上设置不同的 -loop-start 参数以防止重叠。
-messages = 10 设置发送到服务器的消息数量。这是循环测试的另一种方式。而不是通过打开网络连接、XMPP流、身份验证等来重复整个测试,它只会导致多次发送消息。这个参数只被一些发送消息的测试用例接受。对于消息侦听器 - 应该响应消息的测试用例,此处设置的数字指定在测试成功终止之前必须发送响应的次数。
-multi-thread 选项导致在单独的线程中运行测试用例并在所有级别的测试用例中全部继承。通常,您放置参数的测试用例没有测试ID(您在 ‘@’ 和 ‘:’ 字符之间放置的内容),因此它不会自行运行测试。相反,它在内部包含一系列测试用例然后每个线程在单独的线程中运行。这是为许多并发用户运行测试的关键参数。(虽然不是负载测试。)例如,当5人同时修改他们的花名册时,您可以查看服务器是否正确运行。执行将在单独线程中运行的所有继承测试加在一起,并且计算每个单独测试的结果并将其添加到总主测试结果中。
-no-record 用于一种配置测试(任务),用于为以后的测试准备XMPP服务器或数据库。例如,可以创建稍后用于名册测试的测试用户帐户。通常你不想在测试报告中包含这样的测试,并且使用这个参数你基本上从报告中排除了测试。然而,测试和结果显示在命令行输出中,因此您仍然可以跟踪实际发生的情况。
-on-one-socket 是循环测试用例的修饰符。通常,当我们使用 -loop 参数打开循环时,套件会重置状态,关闭网络套接字并从一开始就运行测试,包括打开网络套接字、XMPP流、身份验证等。然而,这个参数改变了这种行为。当测试运行完成(成功)时网络套接字不会关闭,下一次运行只执行测试的最后一部分,同时省略XMPP流初始化、身份验证和除最后之外的所有其他部分。当您想向服务器发送许多消息(尽管此效果也可以使用 -messages 参数来实现)或在服务器上注册许多用户帐户、注销用户帐户和任何其他可能有意义的情况时,这重复多次可能是有意义的。
-port = 5223 该参数与IP地址设置类似,也可以对所有测试进行全局设置。但是,通常您将其设置为仅用于检查SSL连接的选定测试。对于所有其他测试,使用默认端口号。因此,此参数已包含在本节中,而不是”基本测试参数”。
-presence 此参数允许在连接和绑定会话后发送具有正优先级的初始状态。
-repeat-script = 100 和 -repeat-wait = 10 是针对常见测试用例的2个参数。 (从伪xml文本文件中读取测试输入/输出数据的测试用例)。第一个参数是测试循环的另一种变体。它设置测试必须重复多少次。它的工作方式非常类似于 ** -on-one-socket** 参数。唯一的区别是普通测试可以在运行之间保留一些内部状态,因此它可以更好地控制数据。第二个参数以毫秒为单位设置每个人之间的等待/延迟超时测试运行,它是一个与 -delay 非常相似的参数,但它在通用测试中设置了超时。
-source-file = “dir/path/to/file.cot” 是设置”通用测试”脚本文件的参数。常见的测试是依赖于身份验证测试用例的测试用例,可以从文本文件中读取要发送的数据和期望的响应。 “cot”文件是一个伪xml文件,其中包含要发送的节和要期待的节。测试用例将接收到的数据包与文本文件中的数据包进行比较,并报告测试结果。这通常比用Java编写新的测试用例更方便。
当我们期望套接字超时作为测试用例的正确结果时,为测试用例设置 -time-out-ok。通常超时意味着测试失败并且服务器根本没有响应或响应不正确。然而,对于某些测试(例如向通过隐私列表阻止消息的用户发送消息)超时是所需的正确测试结果。
-to-jid = “user_name@host.name“ 为在某处发送数据包的数据包设置目标地址。例如发送 <message/> 数据包的测试用例。您可以设置数据包的目标地址。请注意,通常每个测试都期望对发送的数据有一些响应,因此请确保目标端点将发回测试用例期望的数据。