如果你作为一个程序员还没有使用ChatGPT,那你就错过了!我将向你展示我最喜欢的一个使用ChatGPT的技巧!
我将向你展示我最喜欢的一个使用ChatGPT的小技巧:使用ChatGPT来编写基于属性的测试!
基于属性的测试,A.K.A PBTs,允许你只用一个PBT就能运行数百个单元测试。它通过让你定义一个函数的属性,然后用你的全部输入来运行它,如果你的函数没有通过测试,PBT将找到会使该函数失败的最小值。
从理论上讲,如果你能够测试一个函数的所有属性,那么你的函数现在是不可破译的!这是因为你的函数的属性是不可能的!这是因为你的函数的属性就是你的函数的定义:如果你的定义是完美的,那么这个函数就是完美的!这就是你的函数的定义!
Oooookay,所以我认为这有点令人困惑,所以让我给你看一个例子来代替!
假设我们有一个加法函数:
def add(a, b):
return a + b
进入全屏模式 退出全屏模式
我们通常的测试方法是做这样的事情:
def test_add_1(a, b):
assert add(1, 1) = 2
进入全屏模式 退出全屏模式
但是如果一个奇怪的开发者用这个实现来代替呢?
def add(a, b):
return 2
进入全屏模式 退出全屏模式
很明显,这将通过测试,但在其他情况下会失败。
这就是单元测试失败的原因。你不可能为每一个可能的输入手动编写所有可能的测试。对于基于属性的测试,你可以通过测试函数属性本身来实现这一点。
你可以做的是用基于属性的测试来测试这些属性。
加法的属性之一是identity 属性。无论你把什么数字加到0,它都会返回这个数字。
为了测试这一点,我们可以做这样的事情:
@given(st.floats())
def test_add_identity(a)
assert add(a, 0) == a
进入全屏模式 退出全屏模式
这样做的目的是,对于所有的浮点数,它将测试把这个数加到0是否会一直返回自己。在这个奇怪的实现中,如果a是2,那么它就能工作,但随后PBT会继续测试其他的值,直到它遇到问题。
现在这显然仍有漏洞,但如果你设法测试所有的属性,如交换、关联等,那么你将有一个牢不可破的函数。
现在我们明白了这些测试是多么强大。让我们用ChatGPT来做一个更复杂的例子!
让我们用这个天真的Pearson r实现:
def pearson_correlation_coefficient(x_values, y_values):
x_mean = sum(x_values) / len(x_values)
y_mean = sum(y_values) / len(y_values)
covariance = sum((x - x_mean) * (y - y_mean) for x, y in zip(x_values, y_values)) / len(x_values)
stddev_x = (sum((x - x_mean) ** 2 for x in x_values) / len(x_values)) ** 0.5
stddev_y = (sum((y - y_mean) ** 2 for y in y_values) / len(y_values)) ** 0.5
return covariance / (stddev_x * stddev_y)
进入全屏模式 退出全屏模式
这有明显的bug,但假设你暂时不知道。
要为这些写基于属性的测试,我们可以做使用这个ChatGPT提示:
为以下代码创建基于属性的测试。请全面测试所有的属性和情况,特别是那些会使函数失败的情况。请确保使用文档字符串彻底记录被测试的属性。使用
library作为测试库。代码:
insert code
这个提示为我生成了这些基于属性的测试:
import pytest
from hypothesis import given, strategies as st
@pytest.fixture()
def pearson_corr():
return pearson_correlation_coefficient
@given(st.lists(st.floats()), st.lists(st.floats()))
def test_pearson_correlation_coefficient_valid_input(pearson_corr, x_values, y_values):
"""
Test the pearson_correlation_coefficient function with valid input.
It should return a value between -1 and 1, inclusive.
"""
if len(x_values) < 2 or len(y_values) < 2:
with pytest.raises(ZeroDivisionError):
pearson_corr(x_values, y_values)
else:
result = pearson_corr(x_values, y_values)
assert -1 <= result <= 1
@given(st.lists(st.floats(min_value=-100, max_value=100), min_size=2), st.lists(st.floats(min_value=-100, max_value=100), min_size=2))
def test_pearson_correlation_coefficient_identical_inputs(pearson_corr, x_values, y_values):
"""
Test the pearson_correlation_coefficient function with identical inputs.
It should return 1.
"""
result = pearson_corr(x_values, x_values)
assert result == 1
@given(st.lists(st.floats(min_value=-100, max_value=100), min_size=2), st.lists(st.floats(min_value=-100, max_value=100), min_size=2))
def test_pearson_correlation_coefficient_negative_identical_inputs(pearson_corr, x_values, y_values):
"""
Test the pearson_correlation_coefficient function with identical inputs but with one list negated.
It should return -1.
"""
y_values_neg = [-y for y in y_values]
result = pearson_corr(x_values, y_values_neg)
assert result == -1
@given(st.lists(st.floats(min_value=-100, max_value=100), min_size=2), st.lists(st.floats(min_value=-100, max_value=100), min_size=2))
def test_pearson_correlation_coefficient_orthogonal_inputs(pearson_corr, x_values, y_values):
"""
Test the pearson_correlation_coefficient function with orthogonal inputs.
It should return 0.
"""
x_values_orth = [y for y in y_values]
result = pearson_corr(x_values, x_values_orth)
assert result == 0
@given(st.lists(st.floats(), min_size=1), st.lists(st.floats(), min_size=1))
def test_pearson_correlation_coefficient_zero_division_error(pearson_corr, x_values, y_values):
"""
Test the pearson_correlation_coefficient function with inputs that have zero variance.
It should raise a ZeroDivisionError.
"""
with pytest.raises(ZeroDivisionError):
pearson_corr(x_values, y_values)
@given(st.lists(st.floats()), st.lists(st.floats()))
def test_pearson_correlation_coefficient_same_length(pearson_corr, x_values, y_values):
"""
Test the pearson_correlation_coefficient function with inputs that have different lengths.
It should raise a ValueError.
"""
x_values.pop()
with pytest.raises(ValueError):
pearson_corr(x_values, y_values)
正如你所看到的,使用ChatGPT,生成测试是非常容易的,它可以防止你的代码出现错误。在我作为一个数据工程师的工作中,我几乎每天都在使用它。现在,用你自己的代码试试吧,准备好大吃一惊吧!