在 python 中测试 if-elif-else 条件的有效方法是什么
Whats the efficient way to test if-elif-else conditions in python
我有一堆 python 程序需要评估。该程序的基本框架包含一堆嵌套的 If-elif-else 语句。我想知道什么是最有效的测试方法(生成测试用例)来测试程序。
以下是程序的要点
if month == 1:
if day <= 20:
print("Capricorn")
else:
print("Aquarius")
elif month == 5:
if day <= 21:
print("Taurus")
else:
print("Gemini")
else:
if day <= 21:
print("Sagittarius")
else:
print("Capricorn")
它包含更多的 elif 条件。但我想,你明白了。我想知道,如何生成测试用例或测试涵盖所有条件的代码。
开始编写测试,但包括一个覆盖工具。您可以安装 coverage
package 并直接使用它,或者将它与 nose
或 zope.testrunner
.
等测试运行器一起使用
如果您的测试未能执行任何代码行,它会告诉您;在 运行 您的测试之后,代码覆盖率报告会为您提供覆盖率百分比和您错过的确切行数。
您甚至可以使用 duvet 等其他工具来可视化您可能错过的行,或者与 Jenkins 或 TeamCity 等持续集成工具集成以跟踪一段时间内的覆盖率。
测试几乎总是基于提供输入并期望输出。但在您可以实施测试之前,您需要指定使用您的代码的接口。它是一个图书馆,提供 API 吗?然后直接测试API。也就是说,明确定义外部代码将调用的那些函数或方法,然后以与外部代码使用它们完全相同的方式测试它们。或者它是一个命令行工具?然后测试命令行行为。
如何确保测试嵌套条件结构中的所有不同代码路径?认真思考,并评估,使用coverage analysis tool。
如果你想查看星座,你可以使用类似的东西:
monthday = month * 100 + day
if monthday <= 120:
print("Capricorn")
elif monthday <= 219:
print("Aquarius")
and so on
有一些工具,例如 coverage.py,可以显示您的测试用例是否覆盖了所有代码。但是,当一个程序开始有这么多特例的时候,最好考虑一下重组。
在这种情况下,数据的存储方式可能会产生重大影响。这会用一个 if
语句 :
完成所有逻辑
def classify(month, day):
x = 100*month + day
data = [(120, 218, "Aquarius"), (219, 320, 'Pisces'), (321, 419, "Aries"), (420, 520, "Taurus")]
for start, end, sign in data:
if start <= x <= end:
return sign
现在我们只有一个 if
语句要测试,生成测试用例变得非常容易。
详情
上面的关键是将日历日期变成一个可以轻松测试的数字。人们可以选择一年中的某一天。我选择了 100*month+day
因为它很容易被人类理解和检查。
(以上占星数据明显不完整,其余日期和星座数据为here。)
快速使用方法python-coverage
以下将生成一个漂亮的交互式网页,显示您的测试脚本涵盖或未涵盖哪些语句 test.py
:
python-coverage erase
python-coverage run test.py
python-coverage html "--omit=/usr/share/*"
firefox ./htmlcov/index.html
html 输出样本:
这表明覆盖率为 100%。
对于像这样有很多排列和组合的问题,您应该创建一个包含所有1 个可能输入和预期输出的矩阵,然后创建一个通用测试用例可以遍历 table 的所有行。
为什么是矩阵?因为这是可视化此类场景的最简单方法。例如,如果您有 24 个不同的测试的集合,那么某人将很难快速回答 "do you cover the case of February 29?" 这样的问题。有了 table 中的所有日期和预期值,回答此类问题变得微不足道,并且在代码更改时添加额外的测试用例也变得微不足道。
例如,您首先要为每个月创建一行,因为您的代码似乎是基于日历的。然后,对于每个月,您将为所有重要条件创建行——月初、月末、月内的特殊日期(即:如果 20 日应该给出与 21 日不同的结果,等等)。
您的 table 在概念上可能看起来像这样:
| # month | day | sign
| 1 | 1 | capricorn
| 1 | 20 | capricorn
| 1 | 21 | aquarius
| 5 | 1 | taurus
| 5 | 21 | taurus
| 5 | 22 | gemini
...等等。然后,编写一个可以读取每一行的测试,调用函数,并将输出与预期结果进行比较。
1 "all" 我不一定是全部。您需要定义正常情况和边缘情况,但您不一定要测试每个可能的日期。
我建议将其设为 table 驱动:
testtable = {1: (20, "Capricorn", "Aquarius"),
5: (21, "Taurus", "Gemini")}
def test(month, day):
vals = testtable.get(month,
(21, "Sagittarius", "Capricorn")) # default
print( vals[1 + (day <= vals[0])] )
test(1, 20) # --> Aquarius
test(1, 21) # --> Capricorn
test(3, 21) # --> Capricorn
test(3, 22) # --> Sagittarius
test(5, 21) # --> Gemini
test(5, 22) # --> Taurus
我有一堆 python 程序需要评估。该程序的基本框架包含一堆嵌套的 If-elif-else 语句。我想知道什么是最有效的测试方法(生成测试用例)来测试程序。
以下是程序的要点
if month == 1:
if day <= 20:
print("Capricorn")
else:
print("Aquarius")
elif month == 5:
if day <= 21:
print("Taurus")
else:
print("Gemini")
else:
if day <= 21:
print("Sagittarius")
else:
print("Capricorn")
它包含更多的 elif 条件。但我想,你明白了。我想知道,如何生成测试用例或测试涵盖所有条件的代码。
开始编写测试,但包括一个覆盖工具。您可以安装 coverage
package 并直接使用它,或者将它与 nose
或 zope.testrunner
.
如果您的测试未能执行任何代码行,它会告诉您;在 运行 您的测试之后,代码覆盖率报告会为您提供覆盖率百分比和您错过的确切行数。
您甚至可以使用 duvet 等其他工具来可视化您可能错过的行,或者与 Jenkins 或 TeamCity 等持续集成工具集成以跟踪一段时间内的覆盖率。
测试几乎总是基于提供输入并期望输出。但在您可以实施测试之前,您需要指定使用您的代码的接口。它是一个图书馆,提供 API 吗?然后直接测试API。也就是说,明确定义外部代码将调用的那些函数或方法,然后以与外部代码使用它们完全相同的方式测试它们。或者它是一个命令行工具?然后测试命令行行为。
如何确保测试嵌套条件结构中的所有不同代码路径?认真思考,并评估,使用coverage analysis tool。
如果你想查看星座,你可以使用类似的东西:
monthday = month * 100 + day
if monthday <= 120:
print("Capricorn")
elif monthday <= 219:
print("Aquarius")
and so on
有一些工具,例如 coverage.py,可以显示您的测试用例是否覆盖了所有代码。但是,当一个程序开始有这么多特例的时候,最好考虑一下重组。
在这种情况下,数据的存储方式可能会产生重大影响。这会用一个 if
语句 :
def classify(month, day):
x = 100*month + day
data = [(120, 218, "Aquarius"), (219, 320, 'Pisces'), (321, 419, "Aries"), (420, 520, "Taurus")]
for start, end, sign in data:
if start <= x <= end:
return sign
现在我们只有一个 if
语句要测试,生成测试用例变得非常容易。
详情
上面的关键是将日历日期变成一个可以轻松测试的数字。人们可以选择一年中的某一天。我选择了 100*month+day
因为它很容易被人类理解和检查。
(以上占星数据明显不完整,其余日期和星座数据为here。)
快速使用方法python-coverage
以下将生成一个漂亮的交互式网页,显示您的测试脚本涵盖或未涵盖哪些语句 test.py
:
python-coverage erase
python-coverage run test.py
python-coverage html "--omit=/usr/share/*"
firefox ./htmlcov/index.html
html 输出样本:
这表明覆盖率为 100%。
对于像这样有很多排列和组合的问题,您应该创建一个包含所有1 个可能输入和预期输出的矩阵,然后创建一个通用测试用例可以遍历 table 的所有行。
为什么是矩阵?因为这是可视化此类场景的最简单方法。例如,如果您有 24 个不同的测试的集合,那么某人将很难快速回答 "do you cover the case of February 29?" 这样的问题。有了 table 中的所有日期和预期值,回答此类问题变得微不足道,并且在代码更改时添加额外的测试用例也变得微不足道。
例如,您首先要为每个月创建一行,因为您的代码似乎是基于日历的。然后,对于每个月,您将为所有重要条件创建行——月初、月末、月内的特殊日期(即:如果 20 日应该给出与 21 日不同的结果,等等)。
您的 table 在概念上可能看起来像这样:
| # month | day | sign
| 1 | 1 | capricorn
| 1 | 20 | capricorn
| 1 | 21 | aquarius
| 5 | 1 | taurus
| 5 | 21 | taurus
| 5 | 22 | gemini
...等等。然后,编写一个可以读取每一行的测试,调用函数,并将输出与预期结果进行比较。
1 "all" 我不一定是全部。您需要定义正常情况和边缘情况,但您不一定要测试每个可能的日期。
我建议将其设为 table 驱动:
testtable = {1: (20, "Capricorn", "Aquarius"),
5: (21, "Taurus", "Gemini")}
def test(month, day):
vals = testtable.get(month,
(21, "Sagittarius", "Capricorn")) # default
print( vals[1 + (day <= vals[0])] )
test(1, 20) # --> Aquarius
test(1, 21) # --> Capricorn
test(3, 21) # --> Capricorn
test(3, 22) # --> Sagittarius
test(5, 21) # --> Gemini
test(5, 22) # --> Taurus