-
20-08-2019 - |
문제
저는 과학적인 컴퓨팅 코드(C++로 작성) 작업을 하고 있으며 더 작은 구성 요소에 대한 단위 테스트를 수행하는 것 외에도 "알려진 양호한" 구성 요소와 비교하여 일부 수치 출력에 대해 회귀 테스트를 수행하고 싶습니다. 이전 개정판의 답변.내가 원하는 몇 가지 기능이 있습니다:
- 지정된 허용오차에 대한 숫자 비교 허용(반올림 오류 및 느슨한 기대 모두에 대해)
- int, double 등을 구별하고 필요한 경우 텍스트를 무시하는 기능
- 무엇이 잘못되었고 어디서 문제가 발생했는지 알려주는 올바른 형식의 출력:다중 열 데이터 테이블에서는 서로 다른 열 항목만 표시합니다.
- 반품
EXIT_SUCCESS
또는EXIT_FAILURE
파일이 일치하는지 여부에 따라
이 작업을 수행하는 좋은 스크립트나 응용 프로그램이 있습니까? 아니면 출력 파일을 읽고 비교하기 위해 Python에서 직접 실행해야 합니까?확실히 나는 이런 종류의 요구 사항을 가진 최초의 사람이 아닙니다.
[다음은 엄격하게 관련이 있는 것은 아니지만 무엇을 할지 결정하는 데 영향을 미칠 수 있습니다.저는 CMake와 여기에 포함된 CTest 기능을 사용하여 Google 테스트 프레임워크를 사용하는 단위 테스트를 구동합니다.몇 가지를 추가하는 것이 어렵지 않을 것이라고 생각합니다. 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와 비슷하지만 숫자의 텍스트 파일을 원하는 허용오차와 비교합니다.
파티에 꽤 늦었다는 건 알지만 몇 달 전에 나는 다음과 같은 글을 썼다. nrtest 이 작업 흐름을 더 쉽게 만들기 위한 유틸리티입니다.당신에게도 도움이 될 것 같습니다.
다음은 간단한 개요입니다.각 테스트는 입력 파일과 예상 출력 파일로 정의됩니다.실행 후 출력 파일은 휴대용 벤치마크 디렉터리에 저장됩니다.그런 다음 두 번째 단계에서는 이 벤치마크를 참조 벤치마크와 비교합니다.최근 업데이트를 통해 사용자 확장 기능이 활성화되었으므로 사용자 정의 데이터에 대한 비교 기능을 정의할 수 있습니다.
도움이 되었으면 좋겠습니다.