python 回归测试脚本

2022-05-13 11:12:50 浏览数 (1)

""" ################################################################################ Test a directory of Python scripts, passing command-line arguments, piping in stdin, and capturing stdout, stderr, and exit status to detect failures and regressions from prior run outputs. The subprocess module spawns and controls streams (much like os.popen3 in Python 2.X), and is cross-platform. Streams are always binary bytes in subprocess. Test inputs, args, outputs, and errors map to files in subdirectories.

This is a command-line script, using command-line arguments for optional test directory name, and force-generation flag. While we could package it as a callable function, the fact that its results are messages and output files makes a call/return model less useful.

Suggested enhancement: could be extended to allow multiple sets of command-line arguments and/or inputs per test script, to run a script multiple times (glob for multiple ".in*" files in Inputs?). Might also seem simpler to store all test files in same directory with different extensions, but this could grow large over time. Could also save both stderr and stdout to Errors on failures, but I prefer to have expected/actual output in Outputs on regressions. ################################################################################ """

import os, sys, glob, time from subprocess import Popen, PIPE

configuration args

testdir = sys.argv[1] if len(sys.argv) > 1 else os.curdir forcegen = len(sys.argv) > 2 print('Start tester:', time.asctime()) print('in', os.path.abspath(testdir))

def verbose(args): print('-'80) for arg in args: print(arg) def quiet(*args): pass trace = quiet

glob scripts to be tested

testpatt = os.path.join(testdir, 'Scripts', '*.py') testfiles = glob.glob(testpatt) testfiles.sort() trace(os.getcwd(), *testfiles)

numfail = 0 for testpath in testfiles: # run all tests in dir testname = os.path.basename(testpath) # strip directory path

代码语言:javascript复制
# get input and args
infile = testname.replace('.py', '.in')
inpath = os.path.join(testdir, 'Inputs', infile)
indata = open(inpath, 'rb').read() if os.path.exists(inpath) else b''

argfile = testname.replace('.py', '.args')
argpath = os.path.join(testdir, 'Args', argfile)
argdata = open(argpath).read() if os.path.exists(argpath) else ''

# locate output and error, scrub prior results
outfile = testname.replace('.py', '.out')
outpath = os.path.join(testdir, 'Outputs', outfile)
outpathbad = outpath   '.bad'
if os.path.exists(outpathbad): os.remove(outpathbad)

errfile = testname.replace('.py', '.err')
errpath = os.path.join(testdir, 'Errors', errfile)
if os.path.exists(errpath): os.remove(errpath)

# run test with redirected streams
pypath = sys.executable
command = '%s %s %s' % (pypath, testpath, argdata)
trace(command, indata)

process = Popen(command, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
process.stdin.write(indata)
process.stdin.close()
outdata = process.stdout.read()
errdata = process.stderr.read()                          # data are bytes 
exitstatus = process.wait()                              # requires binary files
trace(outdata, errdata, exitstatus)

# analyze results
if exitstatus != 0:
    print('ERROR status:', testname, exitstatus)         # status and/or stderr
if errdata:
    print('ERROR stream:', testname, errpath)            # save error text 
    open(errpath, 'wb').write(errdata)

if exitstatus or errdata:                                # consider both failure
    numfail  = 1                                         # can get status stderr
    open(outpathbad, 'wb').write(outdata)                # save output to view

elif not os.path.exists(outpath) or forcegen:
    print('generating:', outpath)                        # create first output
    open(outpath, 'wb').write(outdata)

else:
    priorout = open(outpath, 'rb').read()                # or compare to prior
    if priorout == outdata:
        print('passed:', testname)
    else:
        numfail  = 1
        print('FAILED output:', testname, outpathbad)
        open(outpathbad, 'wb').write(outdata)

print('Finished:', time.asctime()) print('%s tests were run, %s tests failed.' % (len(testfiles), numfail))

image.png

0 人点赞