内容简介:Java 测试驱动开发--“井字游戏” 游戏实战
TDD 介绍
TDD是测试驱动开发(Test-Driven Development)的英文简称,是敏捷开发中的一项核心实践和技术,也是一种设计方法论。TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。TDD虽是敏捷方法的核心实践,但不只适用于XP(Extreme Programming),同样可以适用于其他开发方法和过程。
-- 百度百科
准备工具
TDD只是一种开发模式,它并没有用到新的技术。
-
Java : 因为它是主流的编程语言,应用广泛,相关实践也非常多。
-
IntelliJ-IDEA : Java 主流IDE(集成开发工具)。
-
Gradle : 构建工具。
TDD 开发模式
“ 红灯 -- 绿灯 -- 重构 ” 流程是TDD的基石。 这个过程就像打乒乓球,快速的在测试代码和实现代码之间切换。
TDD 开的过程: 每次只考虑一个需求。首先编写一个测试,看看它是否未通过;然后编写实现这个测试的代码,运行所有测试并验证它们是否全部通过;最后,通过重构改进代码。不断重复这个过程,直到成功实现所有需求。
需求
本系列实战 “ 井字游戏 ” ,这是一个非常简单的小游戏。
说明:
是一种在3*3格子上进行的连珠游戏,和五子棋比较类似,由于棋盘一般不画边框,格线排成井字故得名。游戏需要的 工具 仅为纸和笔,然后由分别代表O和X的两个游戏者轮流在格子里留下标记(一般来说先手者为X)。由最先在任意一条直线上成功连接三个标记的一方获胜。
不会玩的同学可以先去完两把: 井字小游戏 。
需求1
先定义边界,以及将棋子放在哪些地方非法。
可将棋子放在3×3棋盘上任何没有棋子的地方。
将需求分成三个测试:
- 如果棋子放在超出了X轴边界的地方,就引发
RuntimeException
异常。 - 如果棋子放在超出了Y轴边界的地方,就引发
RuntimeException
异常。 - 如果棋子放在已经有棋子的地方,就引发
RuntimeException
异常。
测试用例 1
默认你已经会使用 JUnit 单元测试框架了,根据上面的三个测试,我们先来完成第一个。
import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; public class TicTacToeTest { @Rule public ExpectedException exception = ExpectedException.none(); private TicTacToe ticTacToe; @Before public final void before() { ticTacToe = new TicTacToe(); } @Test public void whenXOutsideBoardThenRuntimeException() { exception.expect(RuntimeException.class); ticTacToe.play(5, 2); } }
测试调用 TicTacToe
类的 play()
方法,假设第一个参数是 x 轴,第二个参数是 y 轴,前面需求已经规定,棋盘是3×3的规格,所以参数必须不能小于1或大于3。
x 轴为5会引发异常。在 whenXOutsideBoardThenRuntimeException()
测试用例中,预期这被测代码会抛出 RuntimeException
异常。
实现功能 1
接下来,我们要实现功能代码了,以满足测试用例通过。
public class TicTacToe { public void play(int x, int y) { if (x < 1 || x > 3) { throw new RuntimeException("X is outside board"); } } }
实现代码非常简单,创建 TicTacToe
类和 play()
方法,判断 x 参数,如果小于1或大于3 将抛出 RuntimeException
异常。
** 现在再次执行 测试用例 1 检查它是否运行通过。
测试用例 2
继续在 TicTacToeTest
测试类中创建将的测试用例。
…… @Test public void whenYOutsideBoardThenRuntimeException(){ exception.expect(RuntimeException.class); ticTacToe.play(2,5); }
这条用例用于验证棋盘 y 轴范围抛 RuntimeException
异常。
实现功能 2
继续修改 TicTacToe
的功能代码。使 测试用例2 运行通过。
public class TicTacToe { public void play(int x, int y) { if (x < 1 || x > 3) { throw new RuntimeException("X is outside board"); }else if(y < 1 || y > 3){ throw new RuntimeException("Y is outside board"); } } }
这里针对 play()
方法,增加对参数 y 的判断,如果小于1或大于3则抛出 RuntimeException
异常。
** 现在再次执行 测试用例 2 检查它是否运行通过。
** 另外,保证 测试用例 1 也是可以运行通过的。
测试用例 3
继续在 TicTacToeTest
测试类中创建将的测试用例。
…… @Test public void whenOccupiedThenRuntimeException(){ ticTacToe.play(2,1); exception.expect(RuntimeException.class); ticTacToe.play(2,1); }
如果棋盘上的格子已经被占用,那么不允许再放子上去。
实现功能 3
为了实现测试用例3 ,应该将棋子的位置存储在一个数组中。每当玩家放置新棋子时,都应确认棋子放在未占用的位置,否则引发异常。
public class TicTacToe { private Character[][] board = { {'\0','\0','\0'}, {'\0','\0','\0'}, {'\0','\0','\0'} }; public void play(int x, int y){ if(x < 1 || x > 3){ throw new RuntimeException("X is outside board"); }else if(y < 1 || y > 3){ throw new RuntimeException("X is outside board"); } if(board[x-1][y-1] != '\0'){ throw new RuntimeException("Box is occupied"); }else { board[x-1][y-1] = 'X'; } } }
检查放置棋子的位置是否被占用,如果未占用,就将相应数组元素的值从空(\0)改为占用(X), 注意, 我们还没有记录棋子是谁(X 还是 O)的。
** 再次执行 测试用例 1、2、3 ,使它们全部运行通过。
重构
虽然 TicTacToe
代码已经满足了测试的需求,但是有点令人迷惑。所以需要对现有的代码进行重构。
public class TicTacToe { private Character[][] board = { {'\0','\0','\0'}, {'\0','\0','\0'}, {'\0','\0','\0'} }; public void play(int x, int y){ checkAxis(x); checkAxis(y); setBox(x, y); } private void checkAxis(int axis){ if(axis <1 || axis > 3){ throw new RuntimeException("X is outside board"); } } private void setBox(int x, int y){ if(board[x-1][y-1] != '\0'){ throw new RuntimeException("Box is occupied"); }else { board[x-1][y-1] = 'X'; } } }
这次重构,对paly()的处理逻辑进行了拆分,功能与重构前一样。因为我们有测试代码,所以不用担心重构会带来bug。
** 再次执行 测试用例 1、2、3 ,使它们全部运行通过。
完整实例
最后
本系列中的例子,来自 《Java 测试驱动开发》 一书,我这几天在看,本身不厚,两百多页,内容也不虚,我很讨厌,概念讲的高大上,例子只贴关键代码,这种书根本没法下手操作。而这本书中的例子是可以跟着敲下来的,虽然代码有些小错误。如果感兴趣的同学,可以买正版支持一下,我自己写书,所以知道写书的辛苦。
说说TDD 的感受,就是很爽!
-
看到每次测试用例全部通过很爽!!
-
重构代码很爽!! 因为有测试用例这一牢靠的后盾。
看到这样一张报告,不知道你是否为对自己开发的代码充满了信心。我想这就是 TDD 的魅力!!
完整项目代码: https://github.com/defnngj/TDD
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 游戏开发教程实战:仅仅100行代码教你玩翻四种对弈游戏!
- Kubernetes 学习笔记之阿里云游戏业务实战
- Cocos Creator - 微信小游戏 实战分享
- MicroPython实战:开发一款掷骰子小游戏
- leaf 和cocos creator 游戏实战(二)注册与登陆
- Worktile 技术分享:RxJS实战练习-经典游戏Breakout
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Computational Advertising
by Kushal Dave、Vasudeva Varma / Now Publishers Inc / 2014
Computational Advertising (CA), popularly known as online advertising or Web advertising, refers to finding the most relevant ads matching a particular context on the Web. The context depends on the t......一起来看看 《Computational Advertising》 这本书的介绍吧!