TDD day
在上一篇笔记,您了解了测试驱动的开发可以归结为一个简单的过程,称为TDD Cycle。它有四个步骤,通常被“color coded”,如下所示:
我们称它为“Red-Green-Refactor Cycle”
图片来源
颜色是什麽意思?
不断的循环。
我的笔记会直接跳过playground的章节,建议看完playground的章节再看我的笔记:
the TDD Cycle
clone我的专案,尝试我建制专案的过程吧。
clone Alvin的专案
我希望Login in 的 button ,在帐号与密码不符合规范时,是不能按的。
graph LR;
button.state是disable-->|达成条件|button.state是normal
graph LR;
button.state是normal-->|未达成条件|button.state是disable
为了让程序码有好的可读性,我们在测试的命名要注意
试着遵循一些TDD命名法则。我们来看看范例:
func testAppModel_whenStarted_isInInProgressState() {}
test funtion 的名称应该要描述test。test名称显示在test logs中。当发生错误时,必续邀可以立即了解问题所在。所以要避免test1,test2这种命名。
这里使用的命名方案最多包括四个部分:
我要测试的条件为:
当LoginPageViewController在帐号与密码都已经服合条件时,loginButton的state要是Normal的
func testLoginPageViewController_loginStateIsBothCorrect_loginButtonIsNormal(){}
接着在里面放入三个注解
func testLoginPageViewController_loginStateIsBothCorrect_loginButtonIsNormal(){
//given
// when
//then
}
这是为了方便理解建制这个 Test的流程。
func testLoginPageViewController_loginStateIsBothCorrect_loginButtonIsNormal(){
//given
let state:LoginState = .bothCorrect
// when
//then
}
func testLoginPageViewController_loginStateIsBothCorrect_loginButtonIsNormal(){
//given
let state:LoginState = .bothCorrect
// when
sut.loginState = state
//then
}
func testLoginPageViewController_loginStateIsBothCorrect_loginButtonIsNormal(){
//given
let state:LoginState = .bothCorrect
// when
sut.loginState = state
//then
let loginState = sut.loginPageView.loginButton.state
XCTAssertEqual(loginState, UIButton.State.normal)
}
按下 command + U 开始测试。
结果测试错误,别担心。这是一定会遇到的流程。我们来尝试通过测试。
protocol Loginable {
func changeLoginButtonState(loginState:LoginState)
}
import UIKit
protocol Loginable {
func changeLoginButtonState(loginState:LoginState)
}
class LoginPageViewController: UIViewController{
let loginPageView = LoginPageView()
public var loginState:LoginState = .bothError
//MARK: - loadView()
override func loadView() {
self.view = loginPageView
loginPageView.delegate = self
}
//MARK: - viewDidLoad()
override func viewDidLoad() {
super .viewDidLoad()
}
}
//MARK: Loginable
extension LoginPageViewController:Loginable{
func changeLoginButtonState(loginState: LoginState) {
if loginState == .bothCorrect {
loginPageView.loginButton.isEnabled = true
}
}
}
但是仅仅这样是不够的,我还要能够监测UITextField有没有输入文字,加入UITextField输入的delegate。
import UIKit
protocol Loginable {
func changeLoginButtonState(loginState:LoginState)
}
class LoginPageViewController: UIViewController{
let loginPageView = LoginPageView()
public var loginState:LoginState = .bothError{
didSet{
changeLoginButtonState(loginState: self.loginState)
}
}
//MARK: - loadView()
override func loadView() {
self.view = loginPageView
loginPageView.loginableDelegate = self
loginPageView.usernameTextField.delegate = self
loginPageView.passwordTestField.delegate = self
}
//MARK: - viewDidLoad()
override func viewDidLoad() {
super .viewDidLoad()
}
}
//MARK: Loginable
extension LoginPageViewController:Loginable{
func changeLoginButtonState(loginState: LoginState) {
if loginState == .bothCorrect {
loginPageView.loginButton.isEnabled = true
}
}
}
extension LoginPageViewController:UITextFieldDelegate{
func textFieldDidEndEditing(_ textField: UITextField) {
if textField.text!.count > 10{
loginState = .bothCorrect
changeLoginButtonState(loginState: loginState)
}
}
}
接着 command + U 再测试一次
很好,测试成功了。
我重构了LoginPageViewController,将判断帐号与密码是否输入的逻辑切出去。
import UIKit
protocol Loginable {
func changeLoginButtonState(loginState:LoginState)
}
class LoginPageViewController: UIViewController{
let loginPageView = LoginPageView()
public var loginState:LoginState = .bothError{
didSet{
changeLoginButtonState(loginState: self.loginState)
}
}
//MARK: - loadView()
override func loadView() {
self.view = loginPageView
loginPageView.loginableDelegate = self
loginPageView.usernameTextField.delegate = self
loginPageView.passwordTestField.delegate = self
}
//MARK: - viewDidLoad()
override func viewDidLoad() {
super .viewDidLoad()
}
}
//MARK: Loginable
extension LoginPageViewController:Loginable{
func changeLoginButtonState(loginState: LoginState) {
if loginState == .bothCorrect {
loginPageView.loginButton.isEnabled = true
}
}
}
//MARK: UITextFieldDelegate
extension LoginPageViewController:UITextFieldDelegate{
func textFieldDidEndEditing(_ textField: UITextField) {
let tag = textField.tag
if textField.text!.count > 10{
loginState = loginState.updateState(tag: tag)
}
}
}
我们完成了一次 TDD Cycle,别忘了 TDD 是迭代开发软件的方法,所以这只是第一步,这或许是很漫长的,但是每个扎实的步伐,将会带领你的程序码步向於完美。
下一个 TDD Cycle
<<: NETGEAR WIFI EXTENDER SETUP
大家好! 今天我们要实作的静态函式有点像 Promise 的感觉。 我们进入今天的主题吧! 程序码 ...
WMX3Console 主要用於伺服马达与IO输出输入模拟,很多时候在还没有实际物件(伺服马达,I...
Здравейте,我是Charlie! 在Day16当中,我们完成了前端的购物车新增跟删除,而今天...
昨天提到了 Python,那就不能不介绍资料科学中相当重要、可以说是 Python 懒人包的 Ana...
题号:15 标题:3Sum 难度:Medium Given an integer array num...