可以在未连接到 SIS 的情况下测试 LIS 集成。如果考虑以下要求,则这比测试其他集成类型要复杂得多:a) 绑定到 Web 服务,其要求应用程序管理 SOAP 请求,以及 b) SIS 生成的基于 SOAP 的数据与用于 UI 中“上传文件”选项的数据之间存在数据格式差异。下文将介绍如何使用 LIS 支持 Web 服务和 UI 来测试 LIS 集成。

LIS 2.0 数据格式


LIS 集成测试

如果在将 SIS 连接到集成之前,从功能角度测试 LIS 集成,则您可以在 Learn 的一半集成中确认配置的正确操作。确认 Learn 可以正常处理 LIS 请求后,如果在连接到 SIS 时发生连接或不正确操作方面的问题,则您已经排除了 1/2 的影响因素。在使用提供的示例进行测试后,您可能会考虑从 SIS 中提取 LIS 输出并补充非连接的测试,然后继续将 SIS 连接到 Learn,从而再次限制测试场景中的变量数。

LIS 集成基于 Web 服务,并利用 SOAP 作为数据传输。SOAP 是一种基于 XML 消息格式的协议,可实现结构化信息的交换。

您可以通过两种方式将采用 LIS 格式的数据放置在 Learn 中,即使用 Web 服务端点或上传 xml 文件。


使用 Web 服务端点进行测试

配置完 LIS 集成后,您需要记下 Web 服务端点(会在配置测试环境时用到)。LIS 集成的端点可在配置的 LIS 集成中使用“Web 服务信息”链接进行查找。

此外,您还需要记住您为集成输入的用户名和密码(可从集成菜单中选择“编辑”选项进行查找)。

SoapUI

测试 Web 服务需要使用能够将 SOAP 消息发布到 Web 服务端点的工具。以下示例使用了名为 SoapUI 的工具。您可以访问 www.soapui.org,下载 SoapUI。SoapUI 是一款免费的开源跨平台功能性测试解决方案,可允许您轻松快速地创建和执行 Web 服务功能性负载测试。

以下演示使用了 SoapUI,但您可以使用自己所选的类似工具。

LIS 集成测试完毕后,您便可配置 SIS 以根据必需操作将数据提交到端点。(请参阅服务示例)。

配置 SoapUI

除了 Web 服务信息外,您还需要集成用户名和密码,此类信息可以通过保存的集成对应的编辑菜单访问。此类用户名和密码用于验证对相关 LIS 集成实例的访问权限和识别此实例。

  1. 打开 SoapUI。
  2. 文件菜单中,选择首选项
  3. HTTP 设置下方,选择为传出请求添加验证信息
  4. 选择确定

获取 WSDL URL

测试的每项服务都需要 WSDL 来构建支持的方法。WSDL URL 是“本地 Learn Web 服务”下方管理的“端点 URL”值,与“.wsdl”相连。构建的 WSDL URL 将如下所示:

https://<yourserver>/webapps/bb-data-integration-lis-BBLEARN/services/PersonManagementServiceSyncService .wsdl

您会构建四个此类网址,一个用于要测试的每项服务:

CourseSectionManagerSyncService

GroupManagementSyncService

MembershipManagementSyncService

PersonManagementSyncService

dataSetStatus不是 LIS 服务,而是 Learn 提供的用于监控集成活动的服务。

修复 SoapUI“不支持大于 4 字节的字符”错误

在尝试加载 WSDL 时,一些 SoapUI 安装可能会引发错误“org.apache.xmlbeans.XmlException:java.io.CharConversionException:不支持大于 4 字节的字符:0x96 字节表示长度超过 4 字节”。

要修复此错误,请执行以下操作:

  • 打开 SoapUI 安装下方的“bin”文件夹以及“soapUI-4.6.4.vmoptions”文件。在文本编辑器中将其打开并添加以下一行内容:

    -Dfile.encoding=UTF8

  • 保存该文件,关闭/重新打开 SoapUI,然后再次加载 WSDL。

可能无法通过 SoapUI 采用与批量数据交换管理服务要求访问文件服务器以访问数据文件相同的方式,完成该服务的测试。要了解详情,请稍后参阅本主题中的“使用 SoapUI 测试批量服务”。


创建用于测试的 SoapUI 项目

要测试的每项服务都必须作为项目添加到 SoapUI。下文演示了为测试 PersonManagementServiceSyncService 而进行的 SoapUI 设置。

  1. 使用菜单或“Ctrl+n”,创建新 SoapUI 项目。
  2. 命名该项目。由于此演示是针对人员服务的,因此,我们会将其命名为“LIS 人员”。
  3. 初始 WSDL 字段中,为 PersonManagementServiceSyncService 粘贴上文构建的 WSDL URL。

    初始 WSDL 是您要测试的服务对应的 Learn 端点 URL(带有“.wsdl”扩展名)。

  4. 选择确定
  5. 服务模板创建完毕后,选择项目界面来打开项目的界面查看器。在这里,您将使用从集成的“Web 服务信息”页面复制的 URL 更新服务端点。
  6. 输入集成的配置页面所提供的用户名。
  7. 输入集成的配置页面所提供的密码。

此类信息将用于所有项目的服务。用户名和密码提供了识别目标集成和访问服务所需的验证信息。 

如果您更改“服务端点”设置,则应选择“分配”按钮并选择“-所有请求-”选项来更新项目。如果不这样做,可能会导致 SOAP 错误。

要为课程、成员和小组创建项目,您需要重复第 1-5 步操作。虽然 SoapUI 支持每个项目有多个 WSDL,但如果创建了四个项目,则更容易保持服务分离。


测试集成

SoapUI 根据提供的 WSDL 生成请求模板,虽然此类模板对理解 LIS 管理的对象格式很有用,但不适合提交给 Learn。这样做不会引发问题,Learn 只会返回过程的错误。

要进行测试,必须提交兼容的数据集。下方提供的示例可以用于执行初始测试,之后可以使用从 SIS 中提取的实际数据。

Blackboard Learn 9.1 SP14 及更高版本的 LIS 实施仅支持替换服务,您可以通过提交生成的请求模板来查看支持的服务。不受支持的服务会返回一个 unsupported错误。

测试 PersonManagementServiceSyncService

  1. 在您要测试的服务下方展开界面树(其应该会在创建新项目后显示)。在本示例中, replacePerson将会展开。
  2. 创建新请求并将其命名为 SampleReplacePerson
  3. 请求查看器会打开,其中包含 replacePerson请求的模板。复制 SampleReplacePersonRequest.xml中的文本,并将其粘贴在替换生成的模板的请求视图中。
  4. 选择“提交请求”图标。
  5. 请求结果会显示在您提供的 SOAP XML 右侧的请求视图中。

要使用提供的示例文件测试其余项目/界面,请重复第 1-5 步操作。这样可确保在使用“实际”数据进行测试或连接到 SIS 之前,您的集成配置不会出现任何问题。此外,您可以使用这个过程来测试提取或手动构建的数据集。

系统可能会捕获返回的参考代码来监控请求的处理。


使用 UI 文件上传进行测试

Learn SIS 框架支持通过 UI 上传批量格式化 xml。本演示解释了批量文件与 SIS 提供给 LIS 端点的事件格式之间的区别。

批量文件的文件格式(即用于通过集成 UI 上传的文件)需要经过修改的 xml 版本,而不是 SIS 传递到端点的版本。请在下文可下载的示例集所含的“上传示例”中查看 SampleBulkRequest_PersonCourseMemberTerm.xml。

批量文件格式

当与 LIS 兼容的 SIS 与 Learn 通信时,SIS 会将完全形成的 SOAP 消息发送到 Web 服务端点。此 SOAP 消息包含围绕 LIS XML 数据的包装。此信息不是手动上传数据所必需的,如果包含此信息,则会导致馈送错误。有关人员(用户)对象的截断示例,请参阅下文的“数据集 1.0”。有关每个支持的对象的数据格式完整说明,请参阅 LIS 2.0 数据格式

<?xml version='1.0' encoding='ISO-8859-1'?>
<bulkDataRecord xmlns="http://www.imsglobal.org/services/li...sDataFile_v1p0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.imsglobal.org/services/li...sDataFile_v1p0 ../schemas/imsbdemsDataFile_v1p0.xsd">
<!-- Consider everything ABOVE this line as the "feed file header" -->
  <!-- start persons here -->
  <transactionRecord>
    <transactionOpIdentifier>identifier</transactionOpIdentifier>
    <serviceName>PersonManagementService</serviceName>
    <interfaceName>PersonManager</interfaceName>
    <operationName>replacePerson</operationName>
    <!-- Consider everything ABOVE this line as the "personRecord header";
         operationName will be replacePerson or deletePerson -->
   <parameterSet>
     <parameterRecord>
       <parameterInvoc>In</parameterInvoc>
       <parameterName>sourcedId</parameterName>
       <parameterType>GUID</parameterType>
       <parameterValue>55555</parameterValue&gt; <!-- ID for logging -->
     </parameterRecord>
     <parameterRecord>
       <parameterInvoc>In</parameterInvoc>
       <parameterName>personRecord</parameterName>
       <parameterType>PersonRecord</parameterType>
       <parameterValue>
         <personRecord>
           <sourcedGUID>
             <refAgentInstanceID>unknown</refAgentInstanceID>
             <sourcedId>55555</sourcedId&gt; <!-- batch_uid (for real) -->
           </sourcedGUID>
           <person&gt; <!-- start person record -->
             <formname>
              <formnameType>
                <instanceIdentifier>
                  <language>en</language>
                  <textString>unknown</textString>
                </instanceIdentifier>
                <instanceVocabulary>
                   http://www.imsglobal.org/lis/pmsv2p0/formatnmetypevocabularyv1p0 
                <instanceVocabulary>
                <instanceValue>
                  <language>en</language>
                  <textString>Full</textString>
                </instanceValue>
              </formnameType>
              <formattedName>
                <language>en</language>
                <textString>Dr. First Middle Last, Jr.</textString&gt; <!-- Full Name IGNORED by Learn-->
              </formattedName>
            </formname>
      ...
      </person> 
      </personRecord><!-- end person record -->
      <!-- could have more <personRecord></personRecord>s here -->
    </parameterValue>
</parameterRecord>
</parameterSet>
</transactionRecord>
<!-- could have additional transactionRecords for Courses, Memberships, or Groups here -->
</bulkDataRecord>
 <!-- Master closing tag -->

数据集 1.0:用于在 Learn UI LIS 上传文件中使用的 LIS 示例数据。有关示例集的完整文件,可通过以下链接下载。

更改用于上传的 LIS SOAP XML

批量数据文件的最低要求是,在 LIS 生成的消息中删除 SOAP-ENV:EnvelopeSOAP-ENV:Body 开始标记与结束标记,并将其替换为 bulkDataRecord 开始标记与结束标记。这显示在上文截断的数据集中。如果通过单个文件执行多项事务(例如:人员、课程和成员对应的事务),则必须采用额外的 transactionRecord标记将其封装起来(请参阅完整示例)。

测试

准备好您的数据文件后,通过 LIS 集成菜单打开上传馈送文件

您将会转到上传页面,在这里,您可以选择要上传的文件。对于此演示,选择提供的示例文件:SampleBulkRequest_PersonCourseMemberTerm.xml

提交文件后,您会重新定向回“集成”页面。要查看测试结果,您可以通过管理员 UI 查看创建或更新的对象,或使用 SIS 框架日志查看器来查看集成的日志。

要查看集成的日志,请从集成菜单中选择查看日志,此时,您会转到集成对应的“日志”页面。

要进一步查看日志记录的消息,请在列表中选择消息行项目,详细信息会显示在消息列表下方的“邮件详细内容”区域。

此类详情中将包含对问题调试有用的信息。例如:

<feb _x0032_0=""&gt; Invalid data for attribute: role. Skipping entire record. Reason: The Course Role is invalid.
InvalidData
Error occurred processing the following XML:
In
sourcedId
GUID
test_course.55555
In
membershipRecord
membershipRecord
<membershipRecord><sourcedGUID><refAgentInstanceID>unknown</refAgentInstanceID><sourcedId>test_course.55555</sourcedId></sourcedGUID><membership><collectionSourcedId>test_course</collectionSourcedId><membershipIdType>courseSection</membershipIdType><member><personSourcedId>55555</personSourcedId><role><roleType>Learner</roleType><subRole>Learner</subRole><timeFrame><begin>2014-02-01T15:00:00</begin><end>2014-09-01T15:50:00</end><restrict>false</restrict><adminPeriod><language>en</language><textString>201330</textString></adminPeriod></timeFrame><status>Active</status><dateTime>2011-08-04T15:00:00</dateTime><creditHours>0</creditHours><dataSource>SIS</dataSource><extension><extensionNameVocabulary>unknown</extensionNameVocabulary><extensionTypeVocabulary>unknown</extensionTypeVocabulary><extensionField><fieldName>LIS2.0Role/Gradable</fieldName><fieldType>String</fieldType><fieldValue>Gradable</fieldValue></extensionField><extensionField><fieldName>LIS20DeliverySystem</fieldName><fieldType>String</fieldType><fieldValue>BB</fieldValue></extensionField></extension></role></member><dataSource>SIS</dataSource></membership></membershipRecord></feb>

blackboard.dataintegration.lis.operation.OperationExecutorException: InvalidData

上文的消息详情表示 replaceMembership 操作失败,特别是不正确的课程角色(用黄色高亮文本突出显示)。发布的请求包含在内,但我们可以看到,所提供的角色(即“学习者”)不正确,将其更改为“学生”并重新提交,则会成功发布 replaceMembership 请求。


使用 SoapUI 测试批量服务

为测试批量服务请求而进行的设置与测试其他服务而进行的设置相同,但有一个例外,即您必须提供 Learn 应用程序服务器有权访问的文件服务器,以便通过 LIS 服务“选择”批量数据文件。

批量数据交换 Web 服务的体系结构由以下三个部分组成:客户端(这种情况下为 SoapUI)、测试 Learn 实例中的 LIS 实例和文件服务器。客户端用于将 SOAP 消息发送给批量数据交换 Web 服务。客户端发送的请求包含要处理的批量文件的 URL(位于文件服务器中)以及应执行的操作。

批量数据交换 Web 服务可以针对批量文件执行的可能操作限定在一组 Web 服务操作中,这些操作可由 LIS 实例的其他 Web 服务执行。如果使用的是 9.1 SP 14 及更高版本,则此类操作仅限定为替换操作。

如果您遇到了校验和方面的问题,可以通过“数据集成 - LIS”设置停用校验和检查。

LIS 设置

  1. 打开您配置的 LIS 集成(或创建一个)并记下共享用户名的值。
  2. 集成属性下方,填写并记住以下内容:
    1. 共享的密码
    2. 批处理服务用户名
    3. 批处理服务密码
    4. 批处理下载用户名(例如,将其设为与“批处理服务用户名”相同)
    5. 批处理下载密码(例如,将其设为与“批处理服务密码”相同)
    6. SIS 学习信息服务批处理 Web 服务 URL:http://localhost:8081/
      这是 HTTPD 服务的网址,用于向 LIS 批量服务提供文件且应代表您的特定配置。
  3. 集成状态设为“活动”。
  4. 日志详细程度设为所有诊断和调试消息
  5. Learn 数据源设为针对所有新入站数据使用相同的 Learn 数据源
  6. 选择提交

设置支持 HTTPD 文件服务

下载以下文件并将其解压缩到您将放置测试文件的服务器。

下载 SampleBulkRequest_PersonCourseMemberTerm.xml 文件并将其放在将要传递文件的目录中。

测试 HTTPD 文件服务

java -jar SimpleHttpServer.jar

用法:java SimpleHttpServer <port number> <path to directory to serve files from> <username> <password>

例如:

java -jar SimpleHttpServer.jar 8081 /Users/moneil/Desktop/LISTEST moneil moneil
Server running on port 8081. Hit Ctrl-C to quit.

通过浏览器访问服务器来测试文件的传递。例如:

http://10.0.1.16:8081/SampleBulkRequest_PersonCourseMemberTerm.xml

设置用于测试的 SoapUI

用于测试批量数据交换的 SoapUI 设置与测试其他 LIS 服务而进行的设置相同。

获取批量数据交换 URL/WSDL

  1. 在测试 Learn 实例中导航到“学生信息系统集成”。
  2. LIS 设置区域,选择所创建的 LIS 集成对应的上下文 V 形图标。
  3. 选择 Web 服务信息选项。
  4. WSDL URL 是本地 Learn Web 服务下方批量数据交换管理服务端点 URL 值,与“.wsdl”相连。

SoapUI 设置

  1. 打开 SoapUI。
  2. 文件菜单中,选择首选项
  3. HTTP 设置下方,选择为传出请求添加验证信息
  4. 选择确定
  5. 按 Ctrl+n。
  6. 初始 WSDL 字段中,粘贴 WSDL URL。
  7. 选择确定
  8. 在 announceBulkDataExchange 下方展开界面树(其应该会在创建新项目后显示)。
  9. 服务模板创建完毕后,选择项目界面来打开项目的“界面查看器”。在这里,您可以:
    1. 使用从集成的“Web 服务信息”页面复制的 URL 更新服务端点。
    2. 输入集成的配置页面所提供的用户名。
    3. 输入集成的配置页面所提供的密码。

运行测试

打开 announceBulkDataExchange 请求,并将下文“数据集 2”内容复制/粘贴到请求视图中。

您必须更改示例中的 <ims:url> 元素,以反映您的测试文件服务器!还要确保 URL 位于一行内。

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ims="http://www.imsglobal.org/services/li.../imsbdems_v1p0">
<soapenv:Header>
<ims:imsx_syncRequestHeaderInfo>
<ims:imsx_version>V1.0</ims:imsx_version>
<ims:imsx_messageIdentifier>123456</ims:imsx_messageIdentifier>
</ims:imsx_syncRequestHeaderInfo>
</soapenv:Header>
<soapenv:Body>
<ims:announceBulkDataExchangeRequest>
<ims:transactionId>123456</ims:transactionId>
<ims:bulkBlockManifest>
<ims:bulkBlockManifestId>123456</ims:bulkBlockManifestId>
<ims:expiryDate>2020-10-01T12:00:00</ims:expiryDate>
<ims:bulkBlockDataFile>
<ims:url>http://<your_test_file_server>:8081/<file_path>¬                               /SampleBulkRequest_PersonCourseMemberTerm.xml</ims:url>
<ims:checkSum>b3ecf4f05935c687932ce1d8c1af7335</ims:checkSum>
<ims:totalSize>29063</ims:totalSize>
<ims:savePoint>2020-10-01T12:00:00</ims:savePoint>
<ims:serviceSet>
<ims:serviceRecord>
<ims:serviceName>CourseManagementService</ims:serviceName>
<ims:interfaceName>CourseSectionManager</ims:interfaceName>
<ims:operationSet>
<ims:operationName>replaceCourseSection</ims:operationName>
</ims:operationSet>
</ims:serviceRecord>
</ims:serviceSet>
</ims:bulkBlockDataFile>
</ims:bulkBlockManifest>
</ims:announceBulkDataExchangeRequest>
</soapenv:Body>
</soapenv:Envelope>

数据集 2:BulkDataRequest

创建您自己的测试文件时的注意事项

元素 ims:imsx_messageIdentifierims:transactionIdims:bulkBlockManifestId 都应是同一个值(在本示例中,该值为 123456)。元素 ims:expiryDateims:savePoint 也应是同一个值(在上述示例中,使用了 2020-10-01T12:00:00 值)。

对象 ims:bulkBlockDataFile表示一个要对其执行操作的批处理文件。元素 ims:url是文件服务器中测试馈送文件位置的 URL。元素 ims:totalSize是测试馈送文件的总大小,以字节为单位(在 Linux 中使用“ls -l”,或在 Windows 中使用 dir)。元素 ims:checkSum是测试文件的 md5 哈希值(在 Linux 中使用 md5sum,或在 Windows 中获取类似程序/Cygwin)。

对象 ims:serviceRecord表示馈送文件的处理方式;多个 ims:serviceRecord 可以存在于一个元素 ims:bulkBlockDataFile 中。元素 ims:serviceName表示 LIS Web 服务,在处理指定馈送文件时系统会调用其操作。元素 ims:interfaceName是 LIS SIS 代码所在的界面,其将用作要调用的可用方法的索引。对象 ims:operationSet 包含方法列表(列为 ims:operationName元素),系统将调用其来处理馈送文件。

执行测试请求

可在请求所在的框架左上角选择绿色“执行”按钮,来执行请求。

上述请求的响应如下所示:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<ims:imsx_syncResponseHeaderInfo xmlns:ims="http://www.imsglobal.org/services/li.../imsbdems_v1p0">
<ims:imsx_version>V1.0</ims:imsx_version>
<ims:imsx_messageIdentifier>4ebf713ae3664f84ab67d961c3f55060</ims:imsx_messageIdentifier>
<ims:imsx_statusInfo>
<ims:imsx_codeMajor>success</ims:imsx_codeMajor>
<ims:imsx_severity>status</ims:imsx_severity>
<ims:imsx_messageRefIdentifier>123456</ims:imsx_messageRefIdentifier>
<ims:imsx_description>Use the reference code 9d4a22b81d4a45d683c2c13e0a0e7a1c to track these records in the logs.</ims:imsx_description>
<ims:imsx_codeMinor>
<ims:imsx_codeMinorField>
<ims:imsx_codeMinorFieldName>TargetEndSystem</ims:imsx_codeMinorFieldName>
<ims:imsx_codeMinorFieldValue>fullsuccess</ims:imsx_codeMinorFieldValue>
</ims:imsx_codeMinorField>
</ims:imsx_codeMinor>
</ims:imsx_statusInfo>
</ims:imsx_syncResponseHeaderInfo>
</soapenv:Header>
<soapenv:Body>
<ims:announceBulkDataExchangeResponse xmlns:ims="http://www.imsglobal.org/services/li.../imsbdems_v1p0"/>
</soapenv:Body>
</soapenv:Envelope>


总结

在连接到 SIS 之前手动测试集成,可允许您确认 Learn 配置的正确操作。使用 UI 进行测试可以快速测试数据和设置的行为。使用 SoapUI 工具集进行测试不仅可以测试数据和行为,还能测试从 SIS 中传递的连接和授权设置。这样可允许用于建立和测试 LIS 集成的任务分离。


示例数据

本主题中所用的示例数据集 (bbdn-lis_samples) 可通过 Blackboard GitHub 存储库克隆或下载为 .zip 文件。