-
20-08-2019 - |
質問
私は科学技術計算コード (C++ で書かれた) に取り組んでおり、より小さなコンポーネントの単体テストを実行することに加えて、「既知の正常な」コードと比較することによって数値出力の一部について回帰テストを実行したいと考えています。以前の改訂版からの回答。欲しい機能がいくつかあります。
- 数値を指定された許容値と比較できるようにします (丸め誤差と緩やかな期待値の両方について)
- int、double などを区別し、必要に応じてテキストを無視する機能
- 何が問題で、どこで問題が発生したかを示す、適切にフォーマットされた出力:複数列のデータ表では、異なる列エントリのみを表示します
- 戻る
EXIT_SUCCESS
またはEXIT_FAILURE
ファイルが一致するかどうかに応じて
これを行う優れたスクリプトやアプリケーションはありますか? それとも、出力ファイルを読み取って比較するには、Python で独自のスクリプトやアプリケーションを作成する必要がありますか?確かに、このような要件を持つのは私が初めてではありません。
[以下は厳密には関係ありませんが、何をすべきかの決定に考慮される可能性があります。私は CMake とその埋め込み CTest 機能を使用して、Google Test フレームワークを使用する単体テストを推進しています。いくつか追加するのは難しくないと思います add_custom_command
私の中での発言 CMakeLists.txt
必要な回帰ソフトウェアを呼び出します。]
解決 3
私は、多かれ少なかれ、私が望んで行うにはPythonスクリプトを書いてしまっています。
#!/usr/bin/env python
import sys
import re
from optparse import OptionParser
from math import fabs
splitPattern = re.compile(r',|\s+|;')
class FailObject(object):
def __init__(self, options):
self.options = options
self.failure = False
def fail(self, brief, full = ""):
print ">>>> ", brief
if options.verbose and full != "":
print " ", full
self.failure = True
def exit(self):
if (self.failure):
print "FAILURE"
sys.exit(1)
else:
print "SUCCESS"
sys.exit(0)
def numSplit(line):
list = splitPattern.split(line)
if list[-1] == "":
del list[-1]
numList = [float(a) for a in list]
return numList
def softEquiv(ref, target, tolerance):
if (fabs(target - ref) <= fabs(ref) * tolerance):
return True
#if the reference number is zero, allow tolerance
if (ref == 0.0):
return (fabs(target) <= tolerance)
#if reference is non-zero and it failed the first test
return False
def compareStrings(f, options, expLine, actLine, lineNum):
### check that they're a bunch of numbers
try:
exp = numSplit(expLine)
act = numSplit(actLine)
except ValueError, e:
# print "It looks like line %d is made of strings (exp=%s, act=%s)." \
# % (lineNum, expLine, actLine)
if (expLine != actLine and options.checkText):
f.fail( "Text did not match in line %d" % lineNum )
return
### check the ranges
if len(exp) != len(act):
f.fail( "Wrong number of columns in line %d" % lineNum )
return
### soft equiv on each value
for col in range(0, len(exp)):
expVal = exp[col]
actVal = act[col]
if not softEquiv(expVal, actVal, options.tol):
f.fail( "Non-equivalence in line %d, column %d"
% (lineNum, col) )
return
def run(expectedFileName, actualFileName, options):
# message reporter
f = FailObject(options)
expected = open(expectedFileName)
actual = open(actualFileName)
lineNum = 0
while True:
lineNum += 1
expLine = expected.readline().rstrip()
actLine = actual.readline().rstrip()
## check that the files haven't ended,
# or that they ended at the same time
if expLine == "":
if actLine != "":
f.fail("Tested file ended too late.")
break
if actLine == "":
f.fail("Tested file ended too early.")
break
compareStrings(f, options, expLine, actLine, lineNum)
#print "%3d: %s|%s" % (lineNum, expLine[0:10], actLine[0:10])
f.exit()
################################################################################
if __name__ == '__main__':
parser = OptionParser(usage = "%prog [options] ExpectedFile NewFile")
parser.add_option("-q", "--quiet",
action="store_false", dest="verbose", default=True,
help="Don't print status messages to stdout")
parser.add_option("--check-text",
action="store_true", dest="checkText", default=False,
help="Verify that lines of text match exactly")
parser.add_option("-t", "--tolerance",
action="store", type="float", dest="tol", default=1.e-15,
help="Relative error when comparing doubles")
(options, args) = parser.parse_args()
if len(args) != 2:
print "Usage: numdiff.py EXPECTED ACTUAL"
sys.exit(1)
run(args[0], args[1], options)
他のヒント
あなたは PyUnitではに、今の標準のlibの下の部分であるために行く必要があります名前 unittest
に。それはあなたが尋ねたすべてをサポートしています。許容範囲チェックは、例えばは、 assertAlmostEqual()
にして行われます。
NDIFF のユーティリティは、あなたがしているものに近いかもしれませんそれはdiffのようなものだが、それは希望する許容誤差に番号のテキストファイルを比較します。
:探しています。私はかなり遅れて相手にだけど、数ヶ月前、私はhref="https://nrtest.readthedocs.org" rel="nofollow"> nrtest のユーティリティで
ここでは簡単な概要です。各テストは、その入力ファイルとその期待される出力ファイルで定義されています。実行後、出力ファイルは、ポータブルベンチマークディレクトリに格納されています。第二段階は、基準ベンチマークこのベンチマークを比較します。最近の更新は、ユーザーの拡張機能を有効にしているので、あなたのカスタムデータ用の比較関数を定義することができます。 私はそれが役に立てば幸います。