在我们之前的文章“软件开发 101:从程序员到软件工程师”中,我们讨论了从程序员转变为软件工程师所需的关键技能和知识。在这篇后续文章中,我们将深入探讨软件测试的主题。
我为什么要写测试?我几乎没有足够的时间。
测试是一项投资,当您完成一个项目时,它会多次收回成本。以下是测试带来的一些好处:
- 测试使您有信心改变事物。您甚至被吓呆了要更改深奥的代码块吗?任何人都可以自信地更改经过良好测试的软件。如果更改不好,测试会让您知道。这让开发人员有信心对代码进行更改,因为他们知道测试会捕获这些更改的任何意外后果。
- 测试是文档。测试作为软件文档的一种形式,因为它们描述了软件应该如何运行。这对于正在处理代码的未来开发人员尤其有用。
- 调试变得更快更容易。测试有助于在开发过程中尽早发现缺陷和错误,以免修复起来变得更加困难和耗时。此外,他们可以将错误的搜索范围从整个程序缩小到特定功能。
- 改进协作。测试有助于确保软件的不同部分按预期协同工作。这在大型开发团队中尤其有用,因为它有助于确保一个开发人员所做的更改不会破坏另一个开发人员的工作。
- 更容易维护。随着需求的变化和代码的发展,测试有助于确保软件继续按预期运行。
- 测试提高了软件质量。根据我的经验,不编写测试的人认为这是编写测试的唯一好处。测试捕获代码中的错误和错误,并验证软件是否按预期运行。
软件测试是软件开发过程的一个重要方面,因为它有助于确保软件的高质量并满足用户需求。在 Michael C. Feathers 的名著Working Effectively with Legacy Code中,作者对遗留代码的描述如下:
对我来说,遗留代码只是没有测试的代码。
测试类型
有许多类型的测试,这里是一些最常见的:
- 单元测试:单元测试是一种软件测试,侧重于单独测试单个代码单元,例如函数或方法。它验证每个代码单元是否按预期运行,并有助于在开发过程的早期发现缺陷和错误。单元测试通常是自动化的,并在开发过程中频繁运行,以确保对代码的更改不会破坏现有功能。
- 集成测试:集成测试是一种软件测试,侧重于测试软件不同部分之间的交互。它验证软件的组件是否按预期一起工作,并有助于识别单元测试中可能不明显的问题。集成测试通常在单元测试之后执行,可以自动或手动进行。
- 系统测试:系统测试是一种软件测试,侧重于测试整个软件,而不是单个代码单元。它验证软件在实际场景中使用时是否按预期运行,并有助于识别性能、兼容性和整体功能方面的问题。系统测试通常在集成测试之后执行,可以自动或手动进行。
- 验收测试:验收测试是一种软件测试,侧重于从用户的角度测试软件。它从用户的角度验证软件的行为是否符合预期,并有助于确保软件满足用户要求。验收测试通常在系统测试之后执行,可以自动或手动进行。验收测试的目标是获得利益相关者对软件的认可并确保它已准备好发布。
您可以将这些类型的测试想象成一个金字塔——底部是单元测试(数量最多),顶部是验收测试(最稀缺且运行成本最高)。
import unittest
def calculate_total_cost(items, tax_rate):
# Assume this function calculates the total cost of a list of items, including tax
total = sum(item["price"] for item in items)
total += total * tax_rate
return total
def calculate_item_cost(item, tax_rate):
# Assume this function calculates the cost of a single item, including tax
cost = item["price"] * (1 + tax_rate)
return cost
def fetch_items_from_database(query):
# Assume this function fetches a list of items from a database
items = [{"name": "item1", "price": 10.0},
{"name": "item2", "price": 20.0},
{"name": "item3", "price": 30.0}]
return items
class TestUnit(unittest.TestCase):
# These unit tests check how individual functions work in isolation
def test_calculate_item_cost(self):
item = {"name": "item1", "price": 10.0}
tax_rate = 0.1
expected_cost = 11.0
result = calculate_item_cost(item, tax_rate)
self.assertAlmostEqual(result, expected_cost)
def test_calculate_total_cost(self):
items = [{"name": "item1", "price": 10.0},
{"name": "item2", "price": 20.0},
{"name": "item3", "price": 30.0}]
tax_rate = 0.1
expected_total = 66.0
result = calculate_total_cost(items, tax_rate)
self.assertAlmostEqual(result, expected_total)
def test_fetch_items_from_database(self):
query = "SELECT * FROM items"
expected_items = [{"name": "item1", "price": 10.0},
{"name": "item2", "price": 20.0},
{"name": "item3", "price": 30.0}]
result = fetch_items_from_database(query)
self.assertEqual(result, expected_items)
class TestIntegration(unittest.TestCase):
# This integration test checks how fetch_items_from_database interacts with calculate_total_cost
def test_calculate_total_cost_with_fetch_items(self):
query = "SELECT * FROM items"
items = fetch_items_from_database(query)
tax_rate = 0.1
expected_total = 66.0
result = calculate_total_cost(items, tax_rate)
self.assertAlmostEqual(result, expected_total)
class TestSystem(unittest.TestCase):
# Since our system is so small, this system test is pretty much just our integration test.
# Assume all parts of the system would be in this test case.
def test_calculate_total_cost_with_large_input(self):
items = fetch_items_from_database("SELECT * FROM items") * 1000
tax_rate = 0.1
result = calculate_total_cost(items, tax_rate)
self.assertIsNotNone(result)
def test_calculate_total_cost_with_large_tax_rate(self):
items = fetch_items_from_database("SELECT * FROM items")
tax_rate = 0.9
result = calculate_total_cost(items, tax_rate)
self.assertIsNotNone(result)
class TestAcceptance(unittest.TestCase):
# This acceptance test is supposed to test the software as a user would use it.
def test_calculate_total_cost_with_real_world_input(self):
items = fetch_items_from_database("SELECT * FROM items")
tax_rate = 0.1
result = calculate_total_cost(items, tax_rate)
self.assertAlmostEqual(result, (10.0 + 20.0 + 30.0) * (1 + tax_rate))
def test_calculate_total_cost_with_real_world_tax_rate(self):
items = fetch_items_from_database("SELECT * FROM items")
tax_rate = 0.08
result = calculate_total_cost(items, tax_rate)
self.assertAlmostEqual(result, 64.8)
if __name__ == '__main__':
unittest.main()
测试驱动开发 (TDD)
现在您知道什么是测试以及它们为什么有用,下面是将它们纳入您的开发周期的一种策略。
测试驱动开发 (TDD) 是一种软件开发过程,强调在编写实际代码之前编写自动化测试。该过程涉及为软件的特定行为或功能编写测试,然后编写使测试通过所需的最少代码量。然后针对软件的每个行为或功能重复此方法。
这只是将测试纳入软件开发周期的一种策略,我发现它通常很有效。
标签:软件开发,items,tax,rate,cost,测试,102,total From: https://blog.51cto.com/u_1213352/6052054