单位测试底漆

在为插件创建单元测试时,推荐的实践是将它们存储在Unit_Test文件夹中的插件目录的根级别中。

根文件夹"></a></p>
        <p>对于较大的插件,我们建议将操作,连接,有效载荷和触发器分开到子文件夹中。这将使您可以根据需要运行单独的测试。在单元测试目录中创建子文件夹会影响单元测试导入过程。</p>
        <p><a style=单元测试布局"></a></p>
        <h2 id=创建一个单元测试

单元测试必须符合特定格式。请注意您准备写入单元测试时:

  • TestEncode类必须从TestCase继承
  • 所有测试都是TestEncode类中的函数,它们必须以test_

这是一个正确写入的单元测试的示例:

         
python
1
单元测试进口TestCase
2
3.
TestEncodeTestCase
4
def测试运行自己
5
通过

运行单元测试

写入TestEnclose类后,您可以通过以下方式之一在Pycharm中运行它:

在Pycharm中,单击课程左侧显示的绿色箭头。

从命令行运行测试。有关更多信息,请参阅这里

注意:如果您从命令行运行,您将拥有Python路径问题。要修复此我使用以下代码。

         
python
1
单元测试进口TestCase
2
进口SYS.
3.
进口OS.
4
5
工作_Path.OS.getcwd.
6
SYS.路径插入0“../”
7
8
icon_azure_ad_admin.行动进口DisableUserAccount

这段代码将插件结构的根目录添加到Python路径中。这允许您从icon_目录导入。

没有外部呼叫的单元测试

一旦您的单位测试写入和运行,您就可以开始测试代码。

在测试代码之前,你必须具备以下条件:

  • 有效的plugin.spec.yaml文件
  • 生成的插件
         
python
1
单元测试进口TestCase
2
Komand_Base64.行动进口编码
3.
进口记录
4
5
TestEncodeTestCase
6
def测试运行自己
7
日志记录getlogger.“测试”
8
test_encoder编码
9
10.
参数个数
11.
“内容”“看,妈妈,单元测试!”
12.
13.
14.
test_encoder记录器日志
15.
实际的test_encoder参数个数
16.
17.
预期的'数据''tg9vaybtb20sihvuaxqgdgvzdhmh'
18.
19.
自己assertEqual实际的预期的

接下来,您需要配置以下设置:

  • 记录器
    • 插件需要一个记录器。我们通过导入日志记录和使用logging.getLogger()来执行此操作。感谢Python的魔力,您可以简单地注入其中的课程中 .logger =
  • 参数
    • 如果我们想要运行运行函数,您将需要参数。要快速创建这些,可以从.json测试文件复制它们。(如果你没有那些,那就生成它们./run.sh -c样品
  • 预期的
    • 如果您正在处理复杂的输出,此设置将节省时间。设置期望为" ",然后在assertEqual上设置断点。调试单元测试。它应该在assert语句上中断,并且您将在调试窗格的监视窗口中显示所有变量值。如果实际值是正确的,只需复制值并粘贴到预期的值中。

以下是所有可用的断言陈述:https://docs.python.org/3/library/unittest.html#test-cases.

通常,您将使用assertEquals,但有几个测试断言是有用的,如assertTrue和assertRaises。

用外部呼叫测试

使用外部调用快速发展的方法是使用邮递员来确保您的API调用正确,将该有效载荷复制到插件项目中并将呼叫模拟到API。对于大型复杂呼叫,这可能会产生巨大的节省时间。

假设:您知道如何使用邮递员,可以使用该工具进行API调用。如果你更熟悉这一点,卷曲也会工作。

以下示例来自Office 365电子邮件插件。这是一大吨的代码,但它比它看起来更容易。

这只是简单地将有效负载读取为文本,这使得模拟API调用更加容易。

         
python
1
这只是读取有效载荷作为文本这使得模拟API调用更容易
2
3.
#从文件中获取真正的有效载荷
4
defread_file_to_string文档名称
5
打开文档名称作为my_file.
6
返回my_file.

此代码块模拟请求。要点()方法。Requests.get()方法模拟了一个python命令,使其成为运行测试的有效方法。

         
python
1
#此方法将由模拟使用替换请求。注释
2
defmocked_requests_get.arg游戏Arunachal Pradesh,kwargs
3.
MockResponse
4
def__在里面__自己json_data.status_code
5
自己json_data.json_data.
6
自己status_codestatus_code
7
自己文本"这是一些错误文本"
8
9
defjson自己
10.
返回json负荷自己json_data.
11.
12.
#由于这是从Base Unit_Test文件夹下来的文件夹,因此如果我们是我们的基础路径可能会改变美国
13.
#运行整个套件,或者只是这些测试。
14.
actual_pathOS.路径妄想OS.路径earcath.__file__
15.
实际_joined_pa​​th.OS.路径加入actual_path“有效载荷/ get_messages_from_user.json”
16.
get_messages_from_user_payloadread_file_to_string实际_joined_pa​​th.
17.
18.
如果arg游戏0==.“https://login.microsoftonline.com/test_tenant_id/oauth2/token”
19.
返回MockResponse“Access_Token”“test_api_token6”200.
20.
如果arg游戏0==.“https://graph.microsoft.com/v1.0/test_tenant_id/users/bob@hotmail.com/messages ? $搜索=”:从“& $ = 250 '
21.
返回MockResponseget_messages_from_user_payload200.
22.
23.
打印f“mocked_requests_get未能查找:arg游戏0
24.
返回MockResponse没有任何404

在配置设置时注意以下内容:

  • 模拟对象:
    • 真的,这堂课正在嘲笑两件事。Requests.get()的行为,以及它是响应对象。在此块的前几行中,您将看到我们创建包含在此方法中的内联类。当我们的模拟被调用时,这将是返回的东西。
  • Python路径注意
    • 下面,你会看到我们在有效载荷中读取。我必须用路径做一个技巧,以确保Python可以找到我们的有效负载,而不管在运行此脚本的位置。如果在运行所有测试时从Unit_Tests的根源运行此脚本,则当前工作目录(CWD)将不同于如果您只运行此套件或仅在此套件中进行测试。
  • arg游戏
    • 我看看我们有什么论点,看看我们想要打电话的东西。如果参数符合我们的预期呼叫之一,我会返回模拟响应。
  • 错误
    • 如果传入的参数与我期望的任何URL不匹配,我打印该URL并使用404进行救助。打印会派上用场,这样你就能很快看到失败的地方。404很方便,因为它允许我们测试代码中的错误处理。

在此代码块中,我创建了一个我可以传递到我的操作类的假连接类。

         
python
1
#模拟连接
2
MockConnection
3.
def__在里面__自己
4
自己租户“test_tenant_id”
5
自己auth_token.“test_api_token”
6
7
defget_headers自己api_token
8
返回
9
“thisisaheader”“thisisavalue”
10.
“api_token”自己auth_token.
11.
12.
13.
defget_auth_token.自己
14.
返回自己auth_token.

此代码非常具体于O365插件,但我想记下您必须为我们的插件使用的一些常见类创建模拟类。

最后......实际测试:

         
python
1
@嘲笑修补'requests.get'副作用mocked_requests_get.
2
deftest_get_messages_from_user自己mock_get.
3.
get_messagesGetEmailFromUser
4
get_messages联系MockConnection
5
实际的get_messagesget_messages_from_user“bob@hotmail.com”'$ search =“来自:来自”&$ top = 250'
6
7
自己断言Len.实际的3.
8
自己assertEqual实际的2得到“id”“AAMkADI3Mzc1ZTg3LTIzYWEtNDNmNi1hZDQ5LTBiMjAzYzA3ZThhYwBGAAAAAAAxDvrPc8q6SqGLTJ9iB-SGBwC8UQDN7ObVSLWQuxHJ-dDTAAE-L_Q7AAC8UQDN7ObVSLWQuxHJ-dDTAAE-MJpHAAA = '
  • 模拟补丁
    • 这里的重要事项是@ mock.patch装饰器。这是一个光滑功能,将替换一个功能的行为与您指定的方法。在这种情况下,我们正在接受请求。与上面的Mocked_Requests_get方法替换该功能。

这是有关的更多信息嘲笑

带有例外的单元测试

对于非传统的苔丝单元,我们可以做的最重要的事情之一是异常处理和奇异的错误场景。(想从状态码为200的响应中得到错误的JSON ?这就是如何测试它!)

         
python
1
deftest_make_kql_for_request_throws_exception.自己
2
get_messagesGetEmailFromUser
3.
4
自己assertraises.pluginexception.
5
get_messagesmake_kql_for_request""""""250.

在本例中,我们为make_kql_for_request生成了错误的输入,这将导致它抛出异常。我们希望确保它会抛出一个PluginException,而不是一些用户可能不知道如何处理的其他错误。

打开一个背景允许我们捕获异常并验证我们具有正确的异常。

对触发器的单位测试

自从它们基本上是无穷无尽的循环,难以测试我们的触发器是非常困难的。我们建议您将逻辑从触发器的“主循环”中移动到单独的功能中,并通过直接单元测试测试它们。

最终,您仍然必须验证您的触发器“主循环”。以下示例演示了如何设置呼叫和超时装饰器以确保未达到任何异常。

         
python
1
#超时装饰器允许我们杀死“虽然真实”循环而不发生测试
2
@timeout_pass
3.
@timeout_decorator超时3.
4
@嘲笑修补'requests.get'副作用mocked_requests_get.
5
deftest_microsoft_message_received自己mock_get.
6
先生EmailReceived
7
参数个数
8
“mailbox_id”test_mailbox_id.
9
“project_query”TEST_QUERY
10.
“间隔”1
11.
12.
先生联系mockConnection
13.
先生log_streammockdispatcher.
14.
先生调度程序mockdispatcher.
15.
先生记录器记录getlogger.“TestLogger”
16.
先生当前时间玛雅五月2019 - 08 - 05 t14:57:40z
17.
18.
先生参数个数

@timeout_pass告诉测试框架一个超时正在通过测试

@ timeout_decorator.Timeout(3)-告诉测试在3秒后超时。当interval设为1时,应该会有两个循环足以验证我们通过了这个测试。

附录