😏作者简介:博主是一位测试管理者,同时也是一名对外企业兼职讲师。
📡主页地址:【Austin_zhai】
🙆目的与景愿:旨在于能帮助更多的测试行业人员提升软硬技能,分享行业相关最新信息。
💎声明:博主日常工作较为繁忙,文章会不定期更新,各类行业或职场问题欢迎大家私信,有空必回。
阅读目录
- 1. 目的
- 2. BDD
- 2.1 工作流程
- 2.1.1 需求理解
- 2.1.2 规范定义
- 2.1.3 用例编写
- 2.1.4 测试执行
- 2.1.5 后续优化
- 2.2 用例的编写
- 2.3 脚本实现
- 3. TDD
- 3.1 工作流程
- 3.1.1 编写用例
- 3.1.2 执行用例
- 3.1.3 编写代码
- 3.1.4 执行用例
- 3.1.5 代码重构
- 3.1.6 重复迭代
- 3.2 用例与代码实现
- 4. 后话
1. 目的
web自动化测试作为软件自动化测试领域中绕不过去的一个“香饽饽”,通常都会作为广大测试从业者的首选学习对象,相较于C/S架构的自动化来说,B/S有着其无法忽视的诸多优势,从行业发展趋、研发模式特点、测试工具支持,其整体的完整生态已经远远超过了C/S架构方面的测试价值。
在我们所熟知的自动化测试过程中,除了测试同学之外还有着另外一个非常重要的角色,开发。我们的被测对象的“亲生父母”,那么在自动化测试开展的过程中,如何才能显著提升被测对象的质量与健壮性呢,今天我们就来讲讲与之息息相关的两个开发方法,BDD与TDD。
2. BDD
BDD也就是我们常说的行为驱动开发(Behavior-Driven Development),它是一种基于用户行为的开发方法,强调以用户需求为核心,用自然语言描述用例场景,并在此基础上进行开发和测试。那么在BDD的行为模式下就需要开发人员与产品人员进行紧密的合作,将用户故事和场景描述转化为可执行的测试用例。这样可以确保软件的功能符合用户需求,同时也有助于产品人员更好地理解软件开发过程。从上面我们不难看出这个开发的行为模式下,开发不是拿到产品需求就开始设计概设、详设就开始开发工作的,基于产品的需求之上还要求开发要参照产品与用户的行为与需求,重点根据以用户行为为中心而设计的故事进行侧重开发。我们在BDD模式下将产品故事成为测试用例,而这个测试用例则是需要产品、开发、测试共同进行设计、编写与审核的,这个与我们日常测试活动中所涉及的工作流程会有所不同,所以对于三个团队的紧密合作与沟通要求水准会比较高。
2.1 工作流程
对于BDD模式下项目活动,这个大致的主线与一般的开发模式相同,只不过在每个阶段的执行过程中会有着其独特的特征存在并左右项目的质量优良与否。接下来我们就一起来看一看该模式下的一些基础工作流程。
2.1.1 需求理解
开发团队、测试团队和产品团队需要深入理解用户的需求和期望,包括功能需求、行为规范等。这包括与需求人员的讨论、用户故事编写和使用场景描述等。
2.1.2 规范定义
围绕用户需求,开发团队与产品团队、测试团队一起定义可执行的用户行为规范。这些规范用自然语言描述系统的行为和期望结果,一般采用类似于Gherkin语言的格式进行规范与编写。
2.1.3 用例编写
测试团队根据行为规范编写测试用例,将其转化为可执行的测试脚本。测试用例描述了具体的场景和期望结果,用于验证系统的行为是否符合预期。测试用例应该具有可读性和可理解性,以便业务人员能够理解和参与讨论。
2.1.4 测试执行
测试团队使用适当的自动化测试框架和工具,将测试用例转化为可执行的自动化测试脚本。这些脚本可以模拟用户的行为,与系统交互并验证行为是否符合规范。然后开始执行这些测试脚本,至于是否放在开发本地还是CI环境中都可以。
2.1.5 后续优化
根据测试结果和反馈,测试团队进行迭代和改进,修复问题并改进系统的行为。这包括与产品团队、开发团队的协作和讨论,以确保软件开发朝着正确的方向进行。
从上面的基础流程上来看,大家不难发现,在很多的阶段中测试团队都担任了非常重要的角色,不仅仅要和产品与开发团队保持高度的通过与合作频率,更需要主导大部分的流程工作内容。所以BDD的模式下对于产品的需求与用户行为有着很强的针对性,相较于一般的测试模式,BDD模式在需求理解、沟通和测试用例编写方面具有较为明显的优势,通过强调共同理解、用户需求驱动和自然语言描述的测试用例,提高了团队合作和软件质量。另外该模式对于自动化测试持续改进与优化迭代有很好的兼容性,所以也主要出现在团队的自动化测试活动中。
2.2 用例的编写
故事的编写(用例)是BDD中极其重要的一步,可以说没有一个设计完整的故事,后续就很难高质量的将产品需求覆盖完整,开头方向都错了后续就更加不要指望可以高效高质的完成质量保障工作了。
前面也介绍过了,BDD模式下的故事编写方式一般为类似Gherkin语法的方式,其实可以理解为你将某一个功能的应用场景设计为了一个简单的故事,故事里面会将所有的前情与条件描述清楚,然后根据条件与剧情发展的不同而达成不同的结局,就好像在拍一部电影一样。那么下面就由博主来为大家描述一个简单的故事场景(产品功能使用场景)。
在金融行业中我们经常会接触到需要购买境外基金的情况,那么这样的一个场景我们在BDD模式下应该如何进行用例的编写呢?
场景:普通用户进行境外基金购买
场景描述: 作为一位投资者,用户希望能够成功购买境外基金,以便将资金投资于跨境投资机会。
Given:
用户已登录到其投资账户;
用户已完成合规认证,具备购买境外基金的资格;
账户余额足够购买所选境外基金;
目标基金的代码为 【ABC456】,属于美国市场。
When:
在基金市场页面,用户选择了境外基金 【ABC456】;
用户输入了购买金额 “2000”;
用户选择了购买货币为人民币(CNY);
用户点击购买按钮。
Then:
用户应该看到购买确认页面显示基金的详细信息,包括名称、代码、购买金额和货币类型;
用户确认购买信息无误后,点击确认按钮;
系统应该跳转到境外基金购买流程,并提供用户需要提供的信息;
用户按照指引输入和确认所需的个人身份信息和资金来源信息;
系统应该显示购买成功的提示信息,并更新用户的投资账户余额;
用户的投资账户余额应该减少购买金额 “2000”;
用户的投资账户的交易记录中应该出现一条购买境外基金的记录,包括基金名称、代码、购买金额和货币类型。
以上就是一个基础的BDD模式下的产品故事(测试用例),大家可以看到,它其实就是通过一些关键字(given、when、then)来清晰地描述了测试的场景、条件和预期结果。那么有了这个测试团队可以基于测试用例编写自动化测试脚本,并执行验证功能的正确性和流程的完整性。
2.3 脚本实现
那么基于以上所设计的测试用例,我们就可以在编写脚本的过程中按照实现定好的剧本走向来设计业务流程的走向与其测试点。
具体的整体脚本就不演示了,编写所需要的技巧已经在前几篇文章中介绍过了,这里就直接演示如何根据测试用例来实现测试脚本。
class TestPurchaseOverseasFund(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(10)
def tearDown(self):
self.driver.quit()
def test_purchase_overseas_fund(self):
# 购买境外基金的测试用例
# Given
self.driver.get("https://example.com") # 替换为基金交易平台的URL
self.driver.find_element_by_id("login_username").send_keys("your_username") # 替换为用户名输入框的ID
self.driver.find_element_by_id("login_password").send_keys("your_password") # 替换为密码输入框的ID
self.driver.find_element_by_id("login_button").click() # 替换为登录按钮的ID
self.driver.find_element_by_id("balance").text = "5000" # 替换为账户余额显示元素的ID或选择器
# When
self.driver.find_element_by_id("fund_market").click() # 替换为基金市场入口的ID
self.driver.find_element_by_id("fund_code_input").send_keys("ABC456") # 替换为基金代码输入框的ID
self.driver.find_element_by_id("purchase_amount_input").send_keys("2000") # 替换为购买金额输入框的ID
self.driver.find_element_by_id("currency_dropdown").click() # 替换为货币选择下拉菜单的ID
self.driver.find_element_by_id("currency_cny").click() # 替换为人民币选项的ID
self.driver.find_element_by_id("purchase_button").click() # 替换为购买按钮的ID
# Then
self.assertTrue(self.driver.find_element_by_id("purchase_confirmation").is_displayed()) # 替换为购买确认页面元素的ID或选择器
self.driver.find_element_by_id("confirm_button").click() # 替换为确认按钮的ID
self.assertTrue(self.driver.find_element_by_id("success_message").is_displayed()) # 替换为购买成功提示信息的ID或选择器
self.assertEqual(self.driver.find_element_by_id("balance").text, "3000") # 替换为账户余额显示元素的ID或选择器
self.assertTrue(self.driver.find_element_by_id("transaction_record").is_displayed()) # 替换为交易记录元素的ID或选择器
if __name__ == '__main__':
unittest.main()
3. TDD
TDD相信做测试的大家都应该不陌生,测试驱动开发(Test-Driven Development),这种开发的行为模式的核心主旨就是要求测试同学在开发人员做功能实现的工作之前就完成测试用例的编写,将测试用例做为代编写代码的依照与参考,完成接下去的工作。正所谓字如其名,测试驱动开发。
3.1 工作流程
相较于BDD的开发行为模式,TDD的变化其实非常大,这个可以说在某些特定环节中是基本颠覆了我们日常的项目流程顺序,也正因如此,排除团队与其他不可控因素的影响,TDD模式下产出的产品与项目,其质量与需求完成度可以说是相当之高了。
3.1.1 编写用例
对,你没看错,在这个模式下,一上来就要编写测试用例,但对于大多数测试同学来说,这个却应该不是难事,基于需求编写测试用例早已不是什么稀罕事了。在开发人员进行代码编写的工作前,测试同学就需要早早的开始用例的编写,结束的节点也差不多是开发开始之前再早些时候。而测试用例的内容则与普通测试流程中所需要设计的用例一致。
3.1.2 执行用例
看到这里,大家是不是觉得更离谱了?没有任何代码与程序的前提下为什么要执行测试用例呢?但我想说的是,这是一个不可或缺的验证阶段,检验的当然不是被测对象,而是测试用例本身,确保用例本身可以正确的执行。
3.1.3 编写代码
依照对应功能模块的测试用例,开发人员开始编写对应的代码,这里的目标是编写最少量的代码,以使得当前的测试用例能够通过。这里需要区别开的是,此阶段的代码编写通常关注于满足测试用例的需求,而不是关注整体的实现。
3.1.4 执行用例
基于编译完的功能再次执行测试用例,验证当前编写的功能代码是否通过测试。如果测试用例通过,意味着功能代码满足了需求。如果测试用例失败,说明功能代码存在问题,需要进行修复。其实此步骤的执行流程与普通阶段的基本一致。
3.1.5 代码重构
在功能代码通过测试之后,可以对代码进行重构。重构是指对代码的结构、设计和可读性进行优化,以改进代码的质量和可维护性,而不改变代码的功能。重构后需要再次运行测试用例,确保代码重构没有引入新的错误。
3.1.6 重复迭代
之后的动作基本就是重复以上的这些流程了,以规定好的功能为范围,进行测试驱动开发。
其实可以看出TDD的工作流程是一个持续循环的过程,每个功能都会经历一轮完整的测试、开发、验证和重构。通过频繁运行测试用例,其优势就是开发人员可以尽早发现问题并及时修复,从而保证代码的正确性和可靠性。
3.2 用例与代码实现
用例的写法与普通流程的一致,如果需要了解普通的黑盒用例写法,大家可以翻看之前的测试用例设计相关博文,测试脚本也是类似,不再展开讨论。
4. 后话
无论是BDD也好,还是TDD也罢,并没有所谓的最好的开发行为模式,真正有效的针对各自团队与产品、公司现状而使用以上两种开发行为模式才是正道。如果你的项目需求明确、关注用户行为与产品业务价值的权重比较高,而团队之间又可以高度紧密合作在一起的,BDD模式就是你们产研的不二之选;另一方面,如果你的项目需求较为模糊或变动频繁、业务功能复杂且没有什么试错的空间、同时又需要业务代码又较强的维护性和质量,那么就可以大胆的尝试TDD。当然两者的使用场景不单单如此,更有甚者,将两者结合使用,据项目需求和团队特点进行灵活选择和调整。重要的还是在于如何理解并加之在日常工作中真正的实践总结和反复优化。