重定向tcltest的测试结果

时间:2018-04-09 08:41:03

标签: pipe tcl channel

我喜欢在日常测试任务中使用tcltest。但是测试结果我只能在控制台中看到,因此在每次测试运行后我都需要切换到该控制台,以查找结果。 А根据tcltest文档,有选项 outputChannel 。此选项允许将测试结果重定向到管道或通道,然后显示在我想要的任何位置。 所以我尝试创建这个频道:

set logger [ open "|bash -c \"while true;do sleep 1; while read mess;do  debug=\\\"\$debug \n \$mess\\\";done; if \\\[\\\[ \$debug != \\\"\\\"  \\\]\\\];then notify-send \$debug; debug=\\\"\\\";fi; done \" " r+]

接下来我配置像这样的tcltest:

configure  -singleproc 1 -verbose t -match ** -outputChannel $logger

然后我尝试在我的频道中发送测试消息:

puts $logger  "Test message 1st line \n test message 2 line"

此脚本有效,但在通知中没有显示测试消息,也没有显示tcltest输出。 我如何创建我的记录器频道??

2 个答案:

答案 0 :(得分:0)

这似乎是一个非常复杂的脚本。有了这样的事情,分阶段做就能让生活变得更轻松。第一部分是将Bash脚本放在大括号中并将其存储在变量中:

set notifySendScript {
    while true; do
        sleep 1
        while read mess; do
            sleep 1
            debug="$debug\n$mess"
        done
        if [[ $debug != "" ]]; then
            notify-send $debug
            debug=""
        fi
    done
}

然后你可以更简单地运行你的脚本,它会更加清晰(我已切换到list以便它自动为我们引用内容):

set logger [ open [list |bash -c $notifySendScript] r+]
puts $logger "aaaaaaaa\n bbbbbbb"

现在我们将这些部分分开,我们可以看到你的bash脚本中存在问题。特别是,它重复读取标准输入(因为循环),直到它获得EOF,你的代码从不发送,因为它不是close管道。更有趣的是,它将它置于循环中,以便您的代码将继续尝试在EOF 之后重复读取标准输入,这很不可能是您想要的。还有其他问题(例如,不是从读写管道读取)但我认为最大的问题是你的代码是一个可怕的单行程,当它不需要时,这隐藏了背后的所有问题一面反斜杠和不可读的墙。我强烈建议尝试保持子脚本更整洁(作为单独的文件或至少作为支撑部分,如上所述),因为这会阻止你发疯。

由于您正在尝试将大量输出重定向到它,因此您需要一个更智能的脚本:

set script {
    while read mess; do
        while read -t 1 tail && [ -n $tail ]; do
            mess=`printf '%s\n%s' $mess $tail`
        done
        if [ -n $mess ]; then
            notify-send $mess
        fi
    done
}

set pipeline [open [list |bash -c $script] "w"]
# This could also be an issue; want line buffering because that's what the
# bash script expects, and the default is full buffering (as for *all* channels)
fconfigure $pipeline -buffering line

# Demonstration
puts $pipeline "aaaaaaaa\nbbbbbbb"
after 5000
puts $pipeline "cccccccc\nddddddd"
after 5000
close $pipeline

诀窍是我使用-t选项(用于超时)到read,但仅用于累积额外行的内部循环。此外,它将空行视为发送邮件的借口。最后,外部循环将在获得EOF时终止。允许你正确关闭整个事情是很重要的。

那里存在的另一个问题(在测试中比在部署IMO时更多的问题)是它是一个具有默认缓冲的管道中的面向行的脚本, full 缓冲。我的答案的第二部分中的fconfigure是如何解决这个问题;它让你告诉Tcl一旦准备就发送每一行到管道实现,而不是等待完整的4-8 kB数据。

答案 1 :(得分:0)

您可能希望简化设置并留在Tcl中?使用Tcl的通道转换重定向stdout(由tcltest在引擎盖下使用)是一个方便的选项;并且之前已被覆盖here

此主题有许多变体,但您可能希望开始使用:

步骤1:定义通道拦截器

oo::class create TcltestNotifier {
    variable buffer
    method initialize {handle mode} {
        if {$mode ne "write"} {error "can't handle reading"}
        return {finalize initialize write}
    }
    method finalize {handle} {
        # NOOP
    }

    method write {handle bytes} {
        append buffer $bytes
        return $bytes
    }

    method report {} {
        # sanitize the tcltest report for the notifier
        set buffer [string map {\" \\\"} $buffer]
        # dispatch to notifier (Mac OS X, change to your needs/ OS)
        append cmd "display notification \"$buffer\"" " "
        append cmd "with title \"Tcltest notification\""
        exec osascript -e $cmd
    }
}

以上代码段是Donal直接导出/偷窃的。

第2步:在stdout套件

周围注册tcltest拦截器
package req tcltest
namespace import ::tcltest::*

set tn [TcltestNotifier new]
chan push stdout $tn

test mytest-0.1 "Fails!" -body {
    BARF!;
} -result "?"

chan pop stdout
$tn report

一些评论

  • 您可以改变粒度,请求每个输出行的通知而不是测试报告(然后您必须在write方法中分配给通知程序)。但我怀疑这是否有道理。
  • 该示例构建为在Mac OS X(osascript)上运行,您必须将其修改为* nix工具。