我目前正在开发一个CLI实用程序,我认为通过添加框架可以对其进行大量改进。
基本上,该实用程序围绕许多命令行语法和解析输出。目前,代码分散在各处,包含许多带有硬编码CLI参数的内部run()和readFromRunOutput()调用。
例如:
op=run("command -args");
while(readFromRunOutPUr(op))
{
// Process and take result from output
if(op=="result-one")
dothis();
else if(op=="result-two")
dothat();
}
我想创建一个通用的框架,其中的 以下内容通过XML文件从代码外部输入。 1)测试名称 2)命令行调用 3)成功所需的输出
所以假设一个简单的XML调用......
<Test name=FirstTest>
<CLI="command -args">
<Success Output= "value" >
</Success>
</CLI>
</Test>
是。在上面的例子中有一些问题需要担心,但我想我已经给出了它的要点。基本上我想将所有不同的CLI调用移到代码之外,然后将它们提供给它们(带有成功和失败的标准)。由于很多其他原因,我不能使用任何脚本语言,如perl或python,并且必须使用C / C ++维护产品。
从我收集的要求是
Defined XML syntax
Parser for the above XML spec to memory
Get CLI -----> and invoke
Read Output and compare with the fed in values
(Preferably cross platform support)
这样的实现不仅可以标准化所有不同的单个函数调用,还可以在不进行任何代码更改的情况下轻松扩展。
现在我的问题是,是否有任何现成的免费库(用于C ++)已经提供了类似或基本的模板框架,我可以在其上扩展。优选第一手经验。还有其他指导吗?
答案 0 :(得分:1)
好的,对你真正的问题:
首先,您将需要一个正确的XML解析器(仅使用Qt的XML和XERXES,这可能是您的用例,我不能真正推荐一个,但libxml2似乎被广泛使用)用于您的输入。
如果我理解正确,您只需将CLI
标记的内容传递给命令行,因此不需要解析。你真正的问题似乎是Success Output
,对吧?
如果是这样,你必须回答的第一个问题是这个值意味着什么?如果字符串在输出中的某个位置就足够了吗?上下文是否相关?如果是这样,怎么编码呢?常用表达?或者更确切地说,XML配置中的不同节点如<contains>
,...
根据您需要找到不同解析器的答案。你最有可能使用正则表达式引擎(例如Boost :: regex)。
所有这一切都说,看起来这应该是某种测试框架,你看过可用的替代方案,想到CMake的CTest,可能有很多其他的。
答案 1 :(得分:0)
我不明白你究竟在寻找什么,但看看Boost Program Options。它可以处理大多数开箱即用的CL解析,并且可以在其余部分轻松扩展。
答案 2 :(得分:0)
关于我的确切需要..可能是一个用例会帮助... 让我们说我的工具需要检查“dir”的输出为“file.txt”。我需要编写一个函数来运行命令+解析输出+搜索输入值。现在让我们说另外需要检查“dir”的输出,但这次检查“卷序列号”的值。类似的需要但不一样。 “dir”相同,这次将文件数作为输出。现在我可以坐下来写下并覆盖所有的风景。或者重用一个专用于不同类型命令行解析的现有库。
我希望的第二个用例是将成品交给其他用户(基本上可以重复使用)。因此,如果用户有一个我没有涉及的测试用例,他可以通过已发布的模式添加它(“Dir”..目标值。)
所以基本上我正在寻找一个专用于CLI解析/处理的C / C ++友好库,它具有灵活的输入框架。另一种方法是从头开始自己做。
答案 3 :(得分:0)
我为此使用Glib。他们有很好的方法。
// Declare some file-scope variables
static gint repeats = 2;
static gint max_size = 8;
static gboolean verbose = FALSE;
static gboolean beep = FALSE;
static gboolean rand = FALSE;
// Here you define the options you want
static GOptionEntry entries[] =
{
{ "repeats", 'r', 0, G_OPTION_ARG_INT, &repeats, "Average over N repetitions", "N" },
{ "max-size", 'm', 0, G_OPTION_ARG_INT, &max_size, "Test up to 2^M items", "M" },
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL },
{ "beep", 'b', 0, G_OPTION_ARG_NONE, &beep, "Beep when done", NULL },
{ "rand", 0, 0, G_OPTION_ARG_NONE, &rand, "Randomize the data", NULL },
{ NULL }
};
int main (int argc, char *argv[]){
// You need this for correctly initiate the parser
GError *error = NULL;
GOptionContext *context;
context = g_option_context_new ("- test tree model performance");
g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
g_option_context_add_group (context, gtk_get_option_group (TRUE));
if (!g_option_context_parse (context, &argc, &argv, &error))
{
g_print ("option parsing failed: %s\n", error->message);
exit (1);
}
// Then comes your code
/* ... */
}
在http://developer.gnome.org/glib/2.28/glib-Commandline-option-parser.html了解详情。