# 技术背景

## 随机数的应用

import random
random_number = random.random() # 产生[0,1)之间的均匀随机数
import numpy as np
random_array = random.randn(10) # 产生10个随机数并存储到np格式的一维数组中


# 量子计算产生随机数

# random_number.py
from projectq import MainEngine
from projectq.ops import H, Measure

def random_number_generator():
eng = MainEngine()
qubit = eng.allocate_qubit()
H | qubit
eng.flush()
Measure | qubit
random_number = int(qubit)
eng.flush(deallocate_qubits=True)
return random_number

if __name__ == '__main__':
random_number = random_number_generator()
print ('Random number generated by quantum simulator is: {}'.format(random_number))


[dechin@dechin-manjaro pytest]$python3 random_number.py Random number generated by quantum simulator is: 1 [dechin@dechin-manjaro pytest]$ python3 random_number.py
Random number generated by quantum simulator is: 1
[dechin@dechin-manjaro pytest]$python3 random_number.py Random number generated by quantum simulator is: 0 [dechin@dechin-manjaro pytest]$ python3 random_number.py
Random number generated by quantum simulator is: 0
[dechin@dechin-manjaro pytest]$python3 random_number.py Random number generated by quantum simulator is: 1  在这个案例中，每一次都会产生一个新的随机数0或者1，并且在量子比特使用结束之后，通过eng.flush(deallocate_qubits=True)可以初始化该寄存器，所有的振幅和测量结果都会被丢弃。 ## 注意！！！ 需要注意的是，由于这里我们是使用了模拟器来模拟量子计算机的行为，因此得到的随机数结果还是伪随机数。只有当这一串代码执行在量子处理器上时，我们才能得到真随机数。 # pytest测试 ## 安装pytest库 首先我们可以通过pip来更新安装pytest： [dechin@dechin-manjaro pytest]$ python3 -m pip install -U pytest
Collecting pytest
|████████████████████████████████| 280 kB 464 kB/s
Installing collected packages: pytest
Attempting uninstall: pytest
Found existing installation: pytest 6.2.1
Uninstalling pytest-6.2.1:
Successfully uninstalled pytest-6.2.1
Successfully installed pytest-6.2.2


[dechin@dechin-manjaro pytest]$pytest --version pytest 6.2.2  ## pytest单元测试用例撰写 根据前面一个章节中的random_number.py文件，我们可以对照的写一个简单测试用例： # test_random_number.py import pytest from random_number import random_number_generator as rng def test_random_number_generator(): for i in range(10): random_number = rng() assert random_number == 0 or random_number == 1  该测试用例的含义为：导入rng函数之后，测试10次该函数的返回值，所返回的值必须是0或者1的随机数，如果输出了这两个数字以外的返回结果，那么说明这个随机数产生器功能上存在问题。基于pytest的测试代码可以通过如下的指令来运行： [dechin@dechin-20n2s01200 pytest]$ py.test
=========================================== test session starts ============================================
platform linux -- Python 3.8.5, pytest-6.2.2, py-1.9.0, pluggy-0.13.1
rootdir: /home/dechin/projects/2021-python/pytest
collected 1 item

test_random_number.py .                                                                              [100%]

============================================= warnings summary =============================================
../../../anaconda3/lib/python3.8/site-packages/projectq/ops/_gates.py:118
/home/dechin/anaconda3/lib/python3.8/site-packages/projectq/ops/_gates.py:118: PendingDeprecationWarning: the matrix subclass is not the recommended way to represent matrices or deal with linear algebra (see https://docs.scipy.org/doc/numpy/user/numpy-for-matlab-users.html). Please adjust your code to use regular ndarray.
return np.matrix([[1, 0], [0, 1j]])

../../../anaconda3/lib/python3.8/site-packages/projectq/ops/_gates.py:133
/home/dechin/anaconda3/lib/python3.8/site-packages/projectq/ops/_gates.py:133: PendingDeprecationWarning: the matrix subclass is not the recommended way to represent matrices or deal with linear algebra (see https://docs.scipy.org/doc/numpy/user/numpy-for-matlab-users.html). Please adjust your code to use regular ndarray.
return np.matrix([[1, 0], [0, cmath.exp(1j * cmath.pi / 4)]])

test_random_number.py: 40 warnings
/home/dechin/anaconda3/lib/python3.8/site-packages/projectq/ops/_gates.py:69: PendingDeprecationWarning: the matrix subclass is not the recommended way to represent matrices or deal with linear algebra (see https://docs.scipy.org/doc/numpy/user/numpy-for-matlab-users.html). Please adjust your code to use regular ndarray.
return 1. / cmath.sqrt(2.) * np.matrix([[1, 1], [1, -1]])

-- Docs: https://docs.pytest.org/en/stable/warnings.html
====================================== 1 passed, 42 warnings in 0.50s ======================================


## pytest初始化配置文件

# pytest.ini
[pytest]
filterwarnings =
ignore::PendingDeprecationWarning


[dechin@dechin-manjaro pytest]$py.test =========================================== test session starts ============================================ platform linux -- Python 3.8.5, pytest-6.2.2, py-1.9.0, pluggy-0.13.1 rootdir: /home/dechin/projects/2021-python/pytest, configfile: pytest.ini plugins: cov-2.11.1, metadata-1.11.0, html-3.1.1 collected 1 item test_random_number.py . [100%] ============================================ 1 passed in 0.50s =============================================  这里返回的结果中就没有告警信息了。 ## pytest生成html格式报告 为了更好的展现测试的结果，这里我们需要先安装一个组件pytest-html [dechin@dechin-manjaro pytest]$ python3 -m pip install pytest-html
Collecting pytest-html
Requirement already satisfied: pytest!=6.0.0,>=5.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest-html) (6.2.1)
Requirement already satisfied: attrs>=19.2.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest!=6.0.0,>=5.0->pytest-html) (20.3.0)
Requirement already satisfied: py>=1.8.2 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest!=6.0.0,>=5.0->pytest-html) (1.9.0)
Requirement already satisfied: toml in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest!=6.0.0,>=5.0->pytest-html) (0.10.1)
Requirement already satisfied: packaging in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest!=6.0.0,>=5.0->pytest-html) (20.4)
Requirement already satisfied: pluggy<1.0.0a1,>=0.12 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest!=6.0.0,>=5.0->pytest-html) (0.13.1)
Requirement already satisfied: iniconfig in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest!=6.0.0,>=5.0->pytest-html) (1.1.1)
Requirement already satisfied: six in /home/dechin/anaconda3/lib/python3.8/site-packages (from packaging->pytest!=6.0.0,>=5.0->pytest-html) (1.15.0)
Requirement already satisfied: pyparsing>=2.0.2 in /home/dechin/anaconda3/lib/python3.8/site-packages (from packaging->pytest!=6.0.0,>=5.0->pytest-html) (2.4.7)


[dechin@dechin-manjaro pytest]$py.test --html=pytest_report.html =========================================== test session starts ============================================ platform linux -- Python 3.8.5, pytest-6.2.2, py-1.9.0, pluggy-0.13.1 rootdir: /home/dechin/projects/2021-python/pytest, configfile: pytest.ini plugins: cov-2.11.1, metadata-1.11.0, html-3.1.1 collected 1 item test_random_number.py . [100%] --------- generated html file: file:///home/dechin/projects/2021-python/pytest/pytest_report.html ---------- ============================================ 1 passed in 0.51s =============================================  不过在问题数量并不是很多的情况下，直接看命令行输出也是比较方便的。 ## pytest覆盖率测试 在一个python仓库中我们有可能有非常多的函数、类和文件等，为了保障结果的准确性，我们需要能够给出一个可信的覆盖率测试的结论，只有当覆盖率达到100%时，我们才能认为测试工作已经比较全面的考虑。当然，覆盖率100%的测试，其实并不能保障100%的不出问题，这就是另外的话题了。首先我们又需要补充安装一个组件pytest-cov [dechin@dechin-manjaro pytest]$ python3 -m pip install pytest-cov
Collecting pytest-cov
Collecting coverage>=5.2.1
|████████████████████████████████| 245 kB 15 kB/s
Requirement already satisfied: pytest>=4.6 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest-cov) (6.2.1)
Requirement already satisfied: attrs>=19.2.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest>=4.6->pytest-cov) (20.3.0)
Requirement already satisfied: packaging in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest>=4.6->pytest-cov) (20.4)
Requirement already satisfied: iniconfig in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest>=4.6->pytest-cov) (1.1.1)
Requirement already satisfied: toml in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest>=4.6->pytest-cov) (0.10.1)
Requirement already satisfied: py>=1.8.2 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest>=4.6->pytest-cov) (1.9.0)
Requirement already satisfied: pluggy<1.0.0a1,>=0.12 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest>=4.6->pytest-cov) (0.13.1)
Requirement already satisfied: six in /home/dechin/anaconda3/lib/python3.8/site-packages (from packaging->pytest>=4.6->pytest-cov) (1.15.0)
Requirement already satisfied: pyparsing>=2.0.2 in /home/dechin/anaconda3/lib/python3.8/site-packages (from packaging->pytest>=4.6->pytest-cov) (2.4.7)
Installing collected packages: coverage, pytest-cov
Successfully installed coverage-5.4 pytest-cov-2.11.1


[dechin@dechin-manjaro pytest]$py.test --cov=random_number ./ --cov-report=html =========================================== test session starts ============================================ platform linux -- Python 3.8.5, pytest-6.2.1, py-1.9.0, pluggy-0.13.1 rootdir: /home/dechin/projects/2021-python/pytest, configfile: pytest.ini plugins: cov-2.11.1, metadata-1.11.0, html-3.1.1 collected 1 item test_random_number.py . [100%] ----------- coverage: platform linux, python 3.8.5-final-0 ----------- Coverage HTML written to dir htmlcov ============================================ 1 passed in 0.76s =============================================  这里会提示我们去htmlcov目录下找测试报告，我们打开相应的index.html文件，效果如下： 这里我们看到random_number.py文件的测试覆盖率为86%，我们可以点开链接查看剩下未覆盖的测试是什么内容： 原来是main函数中的几行指令没有被测试到，一般我们在正式仓库中，是需要去掉main函数的，如果不是测试文件的话。 # 使用flake8进行python编码规范检查 首先我们还是使用pip来直接安装flake8组件，其集成了PEP8的python编码规范： [dechin@dechin-manjaro pytest]$ python3 -m pip install -U flake8
Requirement already up-to-date: flake8 in /home/dechin/anaconda3/lib/python3.8/site-packages (3.8.4)


[dechin@dechin-manjaro pytest]$flake8 --version 3.8.4 (mccabe: 0.6.1, pycodestyle: 2.6.0, pyflakes: 2.2.0) CPython 3.8.5 on Linux  使用方式较为简单，在当前目录下直接执行flake8即可，检查项会以当前路径为rootdir，递归的进行检索： [dechin@dechin-manjaro pytest]$ flake8
./test_random_number.py:2:1: F401 'pytest' imported but unused
./test_random_number.py:5:1: E302 expected 2 blank lines, found 1
./random_number.py:5:1: E302 expected 2 blank lines, found 1
./random_number.py:15:1: E305 expected 2 blank lines after class or function definition, found 1
./random_number.py:17:10: E211 whitespace before '('
./random_number.py:17:80: E501 line too long (87 > 79 characters)


# .flake8
[flake8]
exclude = ./test*


[dechin@dechin-manjaro pytest]$flake8 ./random_number.py:5:1: E302 expected 2 blank lines, found 1 ./random_number.py:15:1: E305 expected 2 blank lines after class or function definition, found 1 ./random_number.py:17:10: E211 whitespace before '(' ./random_number.py:17:80: E501 line too long (87 > 79 characters)  我们发现前面出现的关于测试用例中的编码规范，已经不在这个列表的范围了。这个列表中的问题我们一般最好是处理下，但是如果遇到一些判断不需要处理的规范，则同样可以在配置文件中添加相应的规范ID，这里仅作示例使用，前面显示的编码规范问题后面都会改。如下所示就是两个忽略： # .flake8 [flake8] exclude = ./test* ignore = E302, E305  对应的执行结果如下所示： [dechin@dechin-manjaro pytest]$ flake8
./random_number.py:17:10: E211 whitespace before '('
./random_number.py:17:80: E501 line too long (87 > 79 characters)


[dechin@dechin-manjaro pytest]$python3 -m pip install flake8-html Collecting flake8-html Downloading flake8_html-0.4.1-py2.py3-none-any.whl (13 kB) Requirement already satisfied: pygments>=2.2.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from flake8-html) (2.7.2) Requirement already satisfied: flake8>=3.3.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from flake8-html) (3.8.4) Requirement already satisfied: jinja2>=2.9.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from flake8-html) (2.11.2) Requirement already satisfied: importlib-metadata in /home/dechin/anaconda3/lib/python3.8/site-packages (from flake8-html) (2.0.0) Requirement already satisfied: pycodestyle<2.7.0,>=2.6.0a1 in /home/dechin/anaconda3/lib/python3.8/site-packages (from flake8>=3.3.0->flake8-html) (2.6.0) Requirement already satisfied: mccabe<0.7.0,>=0.6.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from flake8>=3.3.0->flake8-html) (0.6.1) Requirement already satisfied: pyflakes<2.3.0,>=2.2.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from flake8>=3.3.0->flake8-html) (2.2.0) Requirement already satisfied: MarkupSafe>=0.23 in /home/dechin/anaconda3/lib/python3.8/site-packages (from jinja2>=2.9.0->flake8-html) (1.1.1) Requirement already satisfied: zipp>=0.5 in /home/dechin/anaconda3/lib/python3.8/site-packages (from importlib-metadata->flake8-html) (3.4.0) Installing collected packages: flake8-html Successfully installed flake8-html-0.4.1  使用方法如下： [dechin@dechin-20n2s01200 pytest]$ flake8 --format=html --htmldir=flake-report
./random_number.py has issues: medium: 4


# .flake8
[flake8]
exclude = ./test*
ignore = W391

# random_number.py
from projectq import MainEngine
from projectq.ops import H, Measure

def random_number_generator():
eng = MainEngine()
qubit = eng.allocate_qubit()
H | qubit
eng.flush()
Measure | qubit
random_number = int(qubit)
eng.flush(deallocate_qubits=True)
return random_number

if __name__ == '__main__':
random_number = random_number_generator()
print('Random number generated by quantum simulator is:\
{}'.format(random_number))



[dechin@dechin-manjaro pytest]$flake8 --format=html --htmldir=flake-report [dechin@dechin-manjaro pytest]$


# 参考链接

posted @ 2021-03-01 00:03  陆言君  阅读(129)  评论(0编辑  收藏