Closed j178 closed 1 year ago
关于solution_test.cpp 我理解你的目的,所有语言都变成一个 stdin -> program -> stdout的测试程序。抹掉了语言的差异,但这样有两个问题:
为了让用户可以专注于逻辑的实现,leetgo需要实现一个调用层
┌────────────────────────────────────────────┐
│leetgo │
│ │
│ ┌─────────────────────────┐ │
│ │ Language native │ │
stdin│ │ │ │stdout
──────►├────────┼────► class Solution─────┼────────►├─────►
│ │ │ │
│ └─────────────────────────┘ │
│ │
└────────────────────────────────────────────┘
理想情况下用户只需要提供 class Solution
,那么leetgo则负责完成(read stdin -> decode as language native),每个语言需要实现一个互操作层
此外,这样把测试放到黑盒里跑了,不利于用户在IDE里打断点调试(指test runner)
不过话说回来,leetcode的测试程序基本也是按这样实现的(stdin, stdout) @yihong0618
是的,一个 docker 的 runtime 但据说要换掉,但这个据说是我两年前听到的
理想情况下用户只需要提供
class Solution
,那么leetgo则负责完成(read stdin -> decode as language native),每个语言需要实现一个互操作层
read stdin -> decode as language native
这应该是 solution_test.cpp
自己做的,例如这样:
int main(int argc, char **argv) {
// scan input args
TreeNode* root; cin >> root;
// initialize object
Solution *obj = new Solution();
// call method
auto &&res = obj->maxDepth(root);
// print result
cout << "$output$" << res << "$output$";
delete obj;
return 0;
}
leetgo 的调用层应该是:
解析 testcases.txt 抽出每个 case 的 input,作为 stdin 调用 executable,捕获 executable 的 stdout 并解析出 output
是与语言无关的。
此外,这样把测试放到黑盒里跑了,不利于用户在IDE里打断点调试(指test runner)
因为 solution_test.cpp
是一个完整的程序,所以用户依然是可以打断点调试的。只是这种情况下没有 leetgo 提供 stdin input,用户需要自己复制粘贴 case 到控制台中。
关于这个问题我有一些想法,但最近比较忙,下周我细说一下
这个 proposal 中的大部分设计都已经在 #116 中实现了,接下来我会来更新 #90 #111 来适配新的测试框架,谢谢各位~
同意这个proposal,但有一个小问题,output wrapper是不是复杂一点比较好? output:
可能还是会和用户的输出有冲突
想了想,把 output marker 改成了 @output:
, 应该足够了,也不会特别奇怪,谢谢你的建议
或者用 @lc output
,跟 code begin/end marker 一致
1. 编译生成 executable (可选) 对于编译型语言,需要现将 `solution_test.cpp` 编译为 binary 才能执行。生成的 binary 应该放在 `/tmp/leetgo_cache/$slug.exec` 。
请问临时目录的路径如何获取,目前项目里是否有这种函数呢
@w43322 Hi, 我在 #126 中添加了一个 getTempBinFile
函数,能帮忙 review 吗?
我最近一直在思考一个更加统一、规范的 local testing 的实现,减少支持新语言所需的开发工作量,让各种语言的 local testing 表现更加一致。
以生成 C++ 版本的
two-sum
为例,我提议做出以下定义:一个 Generator 应该生成什么?
question.md
question.md
包含 Markdown 格式的题目描述,只有当开启code.separate_descrption_file
时才生成这个文件。否则题目描述包含在代码文件中(solution.h
)。See #94 .
testcases.txt
testcases.txt
由多个 case 组成,case 之间由一个空行分隔。case 包括 input 和 output 两部分,如果 input 参数有多个,每行放置一个。
示例:
testcases.txt
中还可能包含一个可选的 Key-value:target_case: 0
,表示只执行某一个 case。case 的编号从 1 开始,向下递增。target_case: 0
中0
表示执行所有 case.-1
代表最后一个 case.solution.h
主要包含经过模板替换、modifier 修改后的 question code snippet, 示例:
solution_test.cpp
solution_test.cpp
应该是一个完整的程序,每次调用执行一个独立的 case。solution_test.cpp
只是逻辑上的概念,并不一定需要生成为单独的文件,可以与代码文件存在于同一个文件中。示例:
为避免用户自己打印到 stdout 的内容影响 output 的解析,return value 的 output 应该包含
output:
前缀,例如:序列化和反序列化的功能实现应该存在于一个公共的 library 中,由
solution_test.cpp
引用。这个 library 应该由 Generator 的Initialize()
拷贝到$outDir/common
中。library 的原始代码应该放在仓库的testutils/$lang
目录下,通过embed
打包在程序中。示例:Click to expand
```cpp #ifndef LC_IO_H #define LC_IO_H #includetest generator
这是
leetgo pick
的工作,它负责:初始化测试环境
包括拷贝 library 代码,初始化语言相关的 workspace (
go mod init
,cargo init
,python -m venv
等)question.md
、testcases.txt
、solution.h
、solution_test.cpp
文件test runner
这是
leetgo test -L
的工作,它负责:编译生成 executable (可选)
对于编译型语言,需要现将
solution_test.cpp
编译为 binary 才能执行。生成的 binary 应该放在/tmp/leetgo/$questionSlug-$langSlug.exec
。解析
testcases.txt
抽出每个 case 的 input,作为 stdin 调用 executable,捕获 executable 的 stdout 并解析出 output比对 output 与 expected output(现阶段是直接的字符串比对,后续可能会支持更智能的判断),展示比对结果。
支持新语言需要的工作
solution_test.$lang
的生成solution_test.$lang
的编译和调用大家怎么看?欢迎一起讨论 @w43322 @frostming @acehinnnqru