分类目录归档:技术笔记

Flask test_client()测试客户端为勾选框传递布尔值数据

今天写单元测试发现了一个常见的问题,即测试时发送POST请求时如何传入布尔值数据(勾选框字段值)?答案是:你没法直接传递布尔值。其实这个答案相当显而易见,客户端当然没法向服务器端发送Python类型的数据,数据的转换是在接受到请求数据后在服务器端进行的。之前在不借助Flask-WTF/WTForms,手动编写表单并处理时就已经注意到了这个问题,不过在测试中不太容易想到。

首先,我们需要了解一下勾选框(<input type="checkbox">)提交的行为:

  • 如果没有勾选,那么勾选框字段的值为空值,而且这个字段不会被序列化到请求中;在服务器端,WTForms会将其转换为False
  • 如果勾选框被勾选,那么传入服务器端的数据会是该字段value属性的值,如果value属性的值为空,那么则提交字符串"on";在服务器端,WTForms会将其转换为True

也就是说,勾选框的数据只要不为空,WTForms就会将其转换为True。所以,在测试中,如果你想让勾选框的值最终转换为True,那么就传入任意字符串;反之则传递空字符串或直接不加入该字段。下面是传入空字符串的示例:

def test_privacy_setting(self):
    self.login()
    response = self.client.post(url_for('user.privacy_setting'), data=dict(
        public_collections='',  # <--
    ), follow_redirects=True)

    user = User.query.get(1)
    self.assertEqual(user.public_collections, False)

顺便说一句,基于勾选框的提交行为,如果没有使用Flask-WTF/WTForms,那么在手动处理提交数据的时候也要进行相应的处理:没有在request.form中获取到勾选框字段(比如,request.form.get('remember')会是None),即表示没有勾选,那么就转换为False;勾选框字段一旦出现,那么就表示勾选,转换为True

在Python Selenium中为Chrome和Firefox浏览器开启headless模式

我们通常会使用Selenium编写UI测试,为浏览器开启Headless模式(执行操作时不显示GUI窗口)会很方便。最新版本的Chrome和Firefox中,均已支持headless模式。

在Selenium中,为这两个浏览器开启headless模式的方式基本相同:

Chrome:

from selenium import webdriver

options = webdriver.ChromeOptions()
options.add_argument('headless')
driver = webdriver.Chrome(options=options)

Firefox:

from selenium import webdriver

options = webdriver.FirefoxOptions()
options.add_argument('headless')
driver = webdriver.Firefox(options=options)

我提交的PR#5120添加了和Chrome相同的导入接口,如果你使用Selenium小于3.8.0版本,则需要将上面的webdriver.FirefoxOptions()替换为webdriver.firefox.options.Options()

另外,你也可以使用环境变量MOZ_HEADLESS 来为Firefox开启headless模式:

import os
from selenium import webdriver

os.environ['MOZ_HEADLESS'] = '1'  # <- this line
driver = webdriver.Firefox()

本文基于我在Stack Overflow的这篇回答:https://stackoverflow.com/a/47481793/5511849

使用Python创建随机文件名

当用户上传文件时,为了进行统一处理,我们可以为所有文件创建随机文件名。Python标准库中的uuid模块很适合用来生成文件名。我一般会使用uuid.uuid4().hex作为随机文件名,因为它会返回16进制字符串形式的uuid,并且不包含连字符,更易读:

import uuid
filename = uuid.uuid4().hex

和其他常见方式的输出对比:

>>> import uuid
>>> uuid.uuid()
UUID('20818854-3564-415c-9edc-9262fbb54c82')
>>> str(uuid.uuid4())
'f705a69a-8e98-442b-bd2e-9de010132dc4'
>>> uuid.uuid4().hex
'5ad02dfb08a04d889e3aa9545985e304'  # <-- this one

这篇文章原发于我在Stack Overflow上的这个回答:https://stackoverflow.com/a/44992275/5511849