You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@devlake.apache.org by GitBox <gi...@apache.org> on 2022/06/27 06:13:55 UTC

[GitHub] [incubator-devlake-website] likyh commented on a diff in pull request #90: Create e2e-test-writing-guide-cn.md

likyh commented on code in PR #90:
URL: https://github.com/apache/incubator-devlake-website/pull/90#discussion_r907009017


##########
docs/09-DeveloperDoc/e2e-test-writing-guide-cn.md:
##########
@@ -0,0 +1,191 @@
+# 如何为插件编写E2E测试
+
+## 为什么要写 E2E 测试
+
+E2E 测试,作为自动化测试的一环,一般是指白盒的集成测试,或者允许使用一些数据库等外部服务的单元测试。书写E2E测试的目的是屏蔽一些内部实现逻辑,仅从数据正确性的角度来看同样的外部输入,是否可以得到同样的输出。另外,相较于黑盒的集成测试来说,可以避免一些网络等因素带来的偶然问题。更多关于插件的介绍,可以在这里获取更多信息: 为什么要编写 E2E 测试(未完成)
+在 DevLake 中,E2E 测试包含接口测试和插件 Extract/Convert 子任务的输入输出结果验证,本篇仅介绍后者的编写流程。
+
+## 准备数据
+
+我们这里以一个简单的插件——飞书会议时长收集举例,他的目录结构目前是这样的。
+![image](https://user-images.githubusercontent.com/3294100/175061114-53404aac-16ca-45d1-a0ab-3f61d84922ca.png)
+接下来我们将进行次插件的 E2E 测试的编写。
+
+编写测试的第一步,就是运行一下对应插件的 Collect 任务,完成数据的收集,也就是让数据库的`_raw_feishu_`开头的表中,保存有对应的数据。
+以下是采用 DirectRun (cmd) 运行方式的运行日志和数据库结果。
+```
+$ go run plugins/feishu/main.go --numOfDaysToCollect 2 --connectionId 1 (注意:随着版本的升级,命令可能产生变化)
+[2022-06-22 23:03:29]  INFO failed to create dir logs: mkdir logs: file exists
+press `c` to send cancel signal
+[2022-06-22 23:03:29]  INFO  [feishu] start plugin
+[2022-06-22 23:03:33]  INFO  [feishu] scheduler for api https://open.feishu.cn/open-apis/vc/v1 worker: 13, request: 10000, duration: 1h0m0s
+[2022-06-22 23:03:33]  INFO  [feishu] total step: 2
+[2022-06-22 23:03:33]  INFO  [feishu] executing subtask collectMeetingTopUserItem
+[2022-06-22 23:03:33]  INFO  [feishu] [collectMeetingTopUserItem] start api collection
+[2022-06-22 23:03:34]  INFO  [feishu] [collectMeetingTopUserItem] finished records: 1
+[2022-06-22 23:03:34]  INFO  [feishu] [collectMeetingTopUserItem] end api collection error: %!w(<nil>)
+[2022-06-22 23:03:34]  INFO  [feishu] finished step: 1 / 2
+[2022-06-22 23:03:34]  INFO  [feishu] executing subtask extractMeetingTopUserItem
+[2022-06-22 23:03:34]  INFO  [feishu] [extractMeetingTopUserItem] get data from _raw_feishu_meeting_top_user_item where params={"connectionId":1} and got 148
+[2022-06-22 23:03:34]  INFO  [feishu] [extractMeetingTopUserItem] finished records: 1
+[2022-06-22 23:03:34]  INFO  [feishu] finished step: 2 / 2
+```
+
+<img width="993" alt="image" src="https://user-images.githubusercontent.com/3294100/175064505-bc2f98d6-3f2e-4ccf-be68-a1cab1e46401.png">
+好的,目前数据已经被保存到了`_raw_feishu_*`表中,`data`列就是插件运行的返回信息。这里我们只收集了最近2天的数据,数据信息并不多,但也覆盖了各种情况,即同一个人不同天都有数据。
+
+另外值得一提的是,插件跑了两个任务,`collectMeetingTopUserItem`和`extractMeetingTopUserItem`,前者是收集数据的任务,是本次需要跑的,后者是解析数据的任务,是本次需要测试的。在准备数据环节是否运行无关紧要。
+
+接下来我们需要将数据导出为.csv格式,这一步很多种方案,大家可以八仙过海各显神通,我这里仅仅介绍几种常见的方案。
+
+### DevLake Code Generator 导出
+
+此方案尚未完工
+
+### GoLand Database 导出
+
+![image](https://user-images.githubusercontent.com/3294100/175067303-7e5e1c4d-2430-4eb5-ad00-e38d86bbd108.png)
+
+这种方案是最简单的,无论使用Postgres或者MySQL,都不会出现什么问题。
+![image](https://user-images.githubusercontent.com/3294100/175068178-f1c1c290-e043-4672-b43e-54c4b954c685.png)
+csv导出的成功标准就是go程序可以无误的读取,因此有以下几点值得注意:
+1. csv文件中的值,可以用双引号包裹,避免值中的逗号等特殊符号破坏了csv格式
+2. csv文件中双引号转义,一般是`""`代表一个双引号
+3. 注意观察data是否是真实值,而不是base64后的值
+
+导出后,将.csv文件放到`plugins/feishu/e2e/raw_tables/_raw_feishu_meeting_top_user_item.csv`。
+
+### MySQL Select Into Outfile
+
+这是 MySQL 将查询结果导出为文件的方案。目前docker-compose.yml中启动的MySQL,是带有--security参数的,因此不允许`select ... into outfile`,首先需要关闭安全参数,关闭方法大致如下图:
+![origin_img_v2_c809c901-01bc-4ec9-b52a-ab4df24c376g](https://user-images.githubusercontent.com/3294100/175070770-9b7d5b75-574b-49ed-9bca-e9f611f60795.jpg)
+关闭后,使用`select ... into outfile`导出csv文件,导出结果大致如下图:
+![origin_img_v2_ccfdb260-668f-42b4-b249-6c2dd45816ag](https://user-images.githubusercontent.com/3294100/175070866-2204ae13-c058-4a16-bc20-93ab7c95f832.jpg)
+可以注意到,data字段多了hexsha字段,需要人工将其转化为字面量。
+
+### Vscode Database
+
+这是 Vscode 将查询结果导出为文件的方案,但使用起来并不容易。以下是不修改任何配置的导出结果
+![origin_img_v2_c9eaadaa-afbc-4c06-85bc-e78235f7eb3g](https://user-images.githubusercontent.com/3294100/175071987-760c2537-240c-4314-bbd6-1a0cd85ddc0f.jpg)
+但可以明显发现,转义符号并不符合csv规范,并且data并没有成功导出,调整配置且手工替换`\"`为`""`后,得到如下结果。
+![image](https://user-images.githubusercontent.com/3294100/175072314-954c6794-3ebd-45bb-98e7-60ddbb5a7da9.png)
+此文件data字段被base64编码,因此需要人工将其解码为字面量。解码成功后即可使用
+
+### MySQL workerbench
+
+此工具必须要自己书写SQL完成数据的导出,可以模仿以下SQL改写:
+```sql
+SELECT id, params, CAST(`data` as char) as data, url, input,created_at FROM _raw_feishu_meeting_top_user_item;
+```
+![image](https://user-images.githubusercontent.com/3294100/175080866-1631a601-cbe6-40c0-9d3a-d23ca3322a50.png)
+保存格式选择csv,导出后即可直接使用。
+
+### Postgres Copy with csv header;
+
+`Copy(SQL语句) to '/var/lib/postgresql/data/raw.csv' with csv header;`是PG常用的导出csv方法,这里也可以使用。
+```sql
+COPY (
+SELECT id, params, convert_from(data, 'utf-8') as data, url, input,created_at FROM _raw_feishu_meeting_top_user_item
+) to '/var/lib/postgresql/data/raw.csv' with csv header;
+```
+使用以上语句,完成文件的导出。如果你的pg运行在docker中,那么还需要使用 `docker cp`命令将文件导出到宿主机上以便使用。
+
+## 编写E2E测试
+
+首先需要创建测试环境,比如这里创建了`meeting_test.go`
+![image](https://user-images.githubusercontent.com/3294100/175091380-424974b9-15f3-457b-af5c-03d3b5d17e73.png)
+接着在其中输入测试准备代码,如下。其大意为创建了一个`feishu`插件的实例,然后调用`ImportCsvIntoRawTable`将csv文件的数据导入`_raw_feishu_meeting_top_user_item`表中。
+```go
+func TestMeetingDataFlow(t *testing.T) {
+	var plugin impl.Feishu
+	dataflowTester := e2ehelper.NewDataFlowTester(t, "feishu", plugin)
+
+	// import raw data table
+	dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_feishu_meeting_top_user_item.csv", "_raw_feishu_meeting_top_user_item")
+}
+```
+导入函数的签名如下:
+```func (t *DataFlowTester) ImportCsvIntoRawTable(csvRelPath string, rawTableName string)```
+他有一个孪生兄弟,仅仅是参数略有区别。
+```func (t *DataFlowTester) ImportCsvIntoTabler(csvRelPath string, dst schema.Tabler)```
+前者用于导入raw layer层的表,后者用于导入任意表。
+**注意:** 另外这两个函数会在导入数据前,先删除数据表并使用`gorm.AutoMigrate`重新表以达到清除表数据的目的。
+
+导入数据完成后,可以尝试运行,目前没有任何测试逻辑,因此一定是PASS的。接着在`TestMeetingDataFlow`继续编写调用调用`extract`任务的逻辑。
+
+```go
+func TestMeetingDataFlow(t *testing.T) {
+	var plugin impl.Feishu
+	dataflowTester := e2ehelper.NewDataFlowTester(t, "feishu", plugin)
+
+	taskData := &tasks.FeishuTaskData{
+		Options: &tasks.FeishuOptions{
+			ConnectionId: 1,
+		},
+	}
+
+	// import raw data table
+	dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_feishu_meeting_top_user_item.csv", "_raw_feishu_meeting_top_user_item")
+
+	// verify extraction
+	dataflowTester.FlushTabler(&models.FeishuMeetingTopUserItem{})
+	dataflowTester.Subtask(tasks.ExtractMeetingTopUserItemMeta, taskData)
+
+}
+```
+新增的代码包括调用`dataflowTester.FlushTabler`刷新会议表,调用`dataflowTester.Subtask`模拟子任务`ExtractMeetingTopUserItemMeta`的运行。

Review Comment:
   fixed



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@devlake.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org