【问题标题】:unit tests for command line args python命令行 args python 的单元测试
【发布时间】:2018-12-03 11:29:58
【问题描述】:

我有一个当前需要 3 个参数的 shell 脚本。我通过带有 shell 脚本文件名、运行 python 脚本的目录以及测试数据目录的名称的 shell 脚本运行它。我希望能够编写一个执行以下命令的单元测试,但前提是我要更改日期,这取决于可用的数据,它会通过或失败。

main_config.sh
yamldir=$1

for yaml in $(ls ${yamldir}/*.yaml | grep -v "export_config.yaml"); do

    if [ "$yaml" != "export_config.yaml" ]; then

        echo "Running export for $yaml file...";
        python valid.py -p ${yamldir}/export_config.yaml -e $yaml -d ${endDate}
        wait

    fi

done

这是在命令行上执行的内容

./main_config.sh /Users/name/Desktop/yaml/ 2018-12-23

这将失败并在终端上输出,因为没有名为 2012-12-23 的目录:

./main_config.sh /yaml/ 2018-12-23
    Running export for apa.yaml file...
    apa.json does not exist

如果目录存在,这将通过并在终端上输出:

Running export for apa.yaml file...
File Name: apa.json Exists 
File Size: 234 Bytes 
Writing to file

我的python脚本脚本如下:

def main(get_config):
    cfg = get_config()[0]  # export_config.yaml
    data = get_config()[1]  # export_apa.yaml
    date = get_config()[2]  # data folder - YYYY-MM-DD

# Conditional Logic


def get_config():
    parser = argparse.ArgumentParser()
    parser.add_argument("-p", "--parameter-file", action="store", required=True)
    parser.add_argument("-e", "--export-data-file", action="store", required=True)
    parser.add_argument("-d", "--export-date", action="store", required=False)
    args = parser.parse_args()

    return [funcs.read_config(args.parameter_file), funcs.read_config(args.export_data_file), args.export_date]


if __name__ == "__main__":
    logging.getLogger().setLevel(logging.INFO)
    main(get_config)

【问题讨论】:

  • 你能说得更具体点吗?编写测试时遇到什么麻烦?
  • 更多的是编写测试的方法。逻辑。我一直在阅读,但这不是测试功能,而是集成测试。 @JETM

标签: python python-2.7 shell unit-testing pytest


【解决方案1】:

在我看来,这不是典型的单元测试(测试函数或方法),而是集成测试(从外部测试子系统)。但当然,您仍然可以使用典型的 Python 测试工具(例如 unittest)来解决这个问题。

一个简单的解决方案是使用subprocess 运行您的脚本,捕获输出,然后将该输出作为测试的一部分进行解析:

import unittest

import os
import sys
if os.name == 'posix' and sys.version_info[0] < 3:
    import subprocess32 as subprocess
else:
    import subprocess

class TestScriptInvocation(unittest.TestCase):

    def setUp(self):
        """call the script and record its output"""
        result = subprocess.run(["./main_config.sh", "/Users/yasserkhan/Desktop/yaml/", "2018-12-23"], stdout=subprocess.PIPE)
        self.returncode = result.returncode
        self.output_lines = result.stdout.decode('utf-8').split('\n')

    def test_returncode(self):
        self.assertEqual(self.returncode, 0)

    def test_last_line_indicates_success(self):
        self.assertEqual(self.output_lines[-1], 'Writing to file')

if __name__ == '__main__':
    unittest.main()

请注意,此代码使用 Python 3 subprocess 模块的反向端口。此外,它尝试解码 result.stdout 的内容,因为在 Python 3 上这将是一个 bytes 对象,而不是在 Python 2 上的 str。我没有测试它,但是这两件事应该是代码可在 2 到 3 之间移动。

另请注意,使用像 "/Users/yasserkhan/Desktop/yaml" 这样的绝对路径很容易破坏,因此您需要找到相对路径或使用环境变量将基本路径传递给您的测试。

您可以添加额外的测试来解析其他行并检查合理的输出,例如预期范围内的文件大小。

【讨论】:

    猜你喜欢
    • 2011-03-13
    • 2012-09-15
    • 1970-01-01
    • 2011-03-18
    • 1970-01-01
    • 2014-03-20
    • 2011-04-29
    • 2011-04-25
    • 1970-01-01
    相关资源
    最近更新 更多