利用Python Mock模拟OJ test case
来源:互联网 发布:坐车软件哪个好 编辑:程序博客网 时间:2024/06/04 18:03
场景需要
在刷OJ的过程中,最常见的就是从stdin里面读取输入了,然后把结果输出到stdout上供OJ判断结果。
一般来说,在本地写完程序之后都会手动输入一遍test case,观察输出结果之后发现不对劲,再手动输入一遍test case。。。
作为一个搞笑的程序员,啊呸,不是,高效的程序员,简直不能忍受一次又一次地手动输入test case,能不能每次debug完之后一键跑数据呢?而且能不能让自己额外想出来的test case保存下来,每次都跑一遍呢?
由于我现在主要是使用Python刷OJ,因此很自然地想到了通过Python Mock来模拟stdin。
例子
以我最近的刷的PAT 1002 A+B for Polynomials (25) Python为例,要完整的模拟整个OJ测试过程主要从两个方面入手,输入和输出。
模拟输入
在Python从console读取输入主要是通过input函数,那么通过一个Mock对象代替掉input函数即可。但是input函数是一个内置函数,怎么Mock呢?
在Python3中,如果要标记内置函数,可以通过builtins包导入;在Python2中,则是通过__builtin__包导入。
Python 3.6.1 (v3.6.1:69c0db5050, Mar 21 2017, 01:21:04)[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwinType "help", "copyright", "credits" or "license" for more information.>>> import builtins>>> builtins.input<built-in function input>Python 2.7.11 (default, Jan 22 2016, 08:29:18)[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwinType "help", "copyright", "credits" or "license" for more information.>>> import __builtin__>>> __builtin__.input<built-in function input>
stackoverflow传送门:Where is the builtin module in Python3? Why was it renamed?
接下来只要在测试函数上加上patch装饰器即可:
class Test1002(object): @patch('builtins.input', lambda: '2 1 2.4 0 3.2') def test_1(self): assert input() == '2 1 2.4 0 3.2'
在上面的代码例子里面我使用一个lambda函数替换了内置函数input,这样就能模拟输入的数据了。
但是还有一个问题,就是运行的程序可能不止调用input一次,可能调用多次,要求每次调用input返回的数据都不一样,这时可以通过一个具有side_effect的Mock类进行模拟。什么是side_effect呢?通过一个实例来说明:
Python 3.6.1 (v3.6.1:69c0db5050, Mar 21 2017, 01:21:04)[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwinType "help", "copyright", "credits" or "license" for more information.>>> from mock import Mock>>> m = Mock(side_effect=['1', '2', '3', '4'])>>> m()'1'>>> m()'2'>>> m()'3'
从例子上来看,就是每次调用具有side_effect的Mock对象都会根据list的顺序返回不同的对象,用来替代input函数的多次输入刚好。
class Test1002(object): @patch('builtins.input', Mock(side_effect=['2 1 2.4 0 3.2', '2 2 1.5 1 0.5'])) def test_2(self): assert input() == '2 1 2.4 0 3.2' assert input() == '2 2 1.5 1 0.5'
捕获输出
OJ基本就是通过stdout输出的数据进行判定,因此如果能把stdout的数据进行重定向即可拿到输出数据。还有另外一种方法是不重定向stdout,但是在stdout之前把数据记录下来。
参考了fluent python中的一个反转sys.stdout.write的例子,我通过一个上下文管理器实现了这个功能。(在离开上下文的时候回复原来的sys.stdout.write)
class PrintRewrite(object): def __init__(self): self.res = '' def __enter__(self): import sys self.origin_write = sys.stdout.write sys.stdout.write = self.log_print return self def log_print(self, text): self.res += text self.origin_write(text) def __exit__(self, exc_type, exc_val, exc_tb): import sys sys.stdout.write = self.origin_write
在每次print之前把print的结果添加到res变量中,因此,如果要检验测试结果:
class Test1002(object): @patch('builtins.input', lambda: '2 1 2.4 0 3.2') def test_1(self): with PrintRewrite() as t: main() assert t.res == '2 1 4.8 0 6.4' @patch('builtins.input', Mock(side_effect=['2 1 2.4 0 3.2', '2 2 1.5 1 0.5'])) def test_2(self): with PrintRewrite() as t: main() assert t.res == '3 2 1.5 1 2.9 0 3.2'
需要注意的是在Python3中,sys.stdout.write方法才可以被重写。在Python2中,write属性是一个只读属性,sys.stdout需要通过一个实现了类似功能的file对象替代才行。
stackoverflow传送门:Set a Read-Only Attribute in Python?
- 利用Python Mock模拟OJ test case
- Python 的mock模拟测试介绍
- 利用OATS技术来设计Test Case
- test case
- Test Case
- spring Mock Test
- Mock in Test
- spring-test 加 mock
- google test mock入门
- Python mock
- 利用python模拟登录
- 单元测试之模拟Mock
- Mock对象-模拟对象
- 数据模拟-mock.js
- express模拟mock数据
- mock.js模拟数据
- Google Test and Google Mock
- Apache Camel Test Framework(MOCK)
- JAVA中的static修饰的方法不能被重写
- 动静分离
- opencv之mixChannels/inRange
- c++ 导入头文件
- zTree的搜索
- 利用Python Mock模拟OJ test case
- ifconfig 不可用
- 基于百度AI的文字识别-Python
- STL中vector<type>的复制
- libcurl console 中文乱码
- 中文分词工具整理
- Position详解
- Java+Selenium3方法篇42-利用POI读写excel文件
- SQL Server CHARINDEX和PATINDEX详解