java测试驱动开发(TDD)之《遥控军舰》

永久更新地址:https://my.oschina.net/bysu/blog/1647738

写在前面:若有侵权,请发邮件by.su@qq.com告知。

本文主要是学习《Java测试驱动开发》过程中的记录,除了工具有点不一致之外,其他都是摘抄自书本。

转载者告知如果本文被转载,但凡涉及到侵权相关事宜,转载者需负责。请知悉!

个人觉得这书相当不错,有兴趣的可以买来看看。

图书的相关链接:http://www.ituring.com.cn/book/1942

书中源码下载:https://download.csdn.net/download/gdzjsubaoya/10286870

开发“遥控军舰”

1.创建项目

书中主要是通过git导入项目到IntelliJ IDEA中,不过由于本人是用eclipse,所以我通过上面的网址下载了源码自本地,在eclipse中创建了一个gradle项目,然后把源码放到里面相关目录(没有试过导入书中的项目会怎样,因为书中用的是IntelliJ IDEA + gradle+TestNG,感兴趣的可以自己试一下)

工具:eclipse+gradle+TestNG,整个项目目录如下:

134129_gHNp_2910125.png

2.辅助类

假设这个项目最初是由你的一位同事开发的,他是位卓越的程序员和TDD践行者,你深信他编写的测试有极高的代码覆盖率。换言之,你完全可以依赖他已做的工作。然而,这位同事还未完成这个项目就去度假了,余下的工作将由你接手完成。他创建了所有辅助类: Direction、Location、Planet 和Point。你注意到相应的测试类也已编写好,它们的名称与被测试的类相同,但包含后缀Spec (如Directionspec )。使用这个后缀旨在明确这样一点: 它们不仅用于验证代码,还是可执行的规范。

除这些辅助类外,还有另外两个类: Ship (实现) 和shipspec (规范测试),你的大部分时间都将花在完善它们上。你将在ShipSpec中编写测试,再在Sh ip类中编写实现代码( 与本书前面做的完全相同)。

我们知道,测试不仅提供了验证代码的途径,还是可执行的文档。因此从现在开始,我们将测试称为“规范”。

每次编写规范或实现规范的代码后,我们都将运行测试。

项目创建完毕,着手第一个需求。

3.需求1

要移动军舰,需要知道它当前的位置;另外,还需知道军舰面向哪个方向:北、南、东还是西。因此,第一个需求如下:

给定军舰的起始位置(x,y)以及它面向的方向(N、S、E或W)。

处理这个需求前,先看一下可使用的辅助类。Point类存储了坐标x和y,其构造函数如下:

public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

还有枚举类Directiion,它定义的值如下:

public enum Direction {

    NORTH(0, 'N'),
    EAST(1, 'E'),
    SOUTH(2, 'S'),
    WEST(3, 'W'),
    NONE(4, 'X');
}

最后,还有Location类,其构造函数将前述两个类的对象作为参数:

public Location(Point point, Direction direction) {
        this.point = point;
        this.direction = direction;
}

知道这些后,为第一个需求编写测试就非常容易。你应该像前一章那样做。

请尝试自己编写规范,完成后再将其与本书提供的解决方案进行比较。对于实现规范的代码,也这样做:城市自己编写它们,完成后再与我们提供的解决方案进行比较。

1.规范

这个需求的规范如下:

@Test
public class ShipSpec {
	public void whenInstantiatedThenLocationIsSet(){
		Location location = new Location(new Point(21, 13), Direction.NORTH);
		Ship ship = new Ship(location);
		assertEquals(ship.getLocation(), location);
	}

}

这个规范很简单,我们 只做了这样的检查:传递给构造函数Ship的Location对象是否被存储;能否通过获取函数getLocation访问它。

注解@Test

使用TestNG时,在类级指定注解@Test后,无需再指定应将哪些方法视为测试。在这里,所有的共有方法都被视为TestNG测试。

2.实现

这个规范的实现非常简单,只需将构造函数的参数赋给变量location即可:

public class Ship {
	
	private final Location location;
	
	public Ship(Location location){
		this.location = location;
	}
	
	public Location getLocation(){
		return location;
	}
}

3.重构

我们知道,需要为每个规范实例化Ship,因此需要重构规范类,在其中添加一个用@BeforeMethod注解的方法。如下所示:

import org.testng.annotations.*;
import static org.testng.Assert.*;

@Test
public class ShipSpec {
	
	private Ship ship;
	private Location location;
	
	@BeforeMethod
	public void beforeTest(){
		location = new Location(new Point(21, 13), Direction.NORTH);
		ship = new Ship(location);
	}
	
	
	public void whenInstantiatedThenLocationIsSet(){
		/*Location location = new Location(new Point(21, 13), Direction.NORTH);
		Ship ship = new Ship(location);*/
		assertEquals(ship.getLocation(), location);
	}
}

我们没有引入任何新的行为,而只将部分代码移到了用@BeforeMethod注解的方法中,以免编写后面的规范时重复这些代码。这样,运行每个测试时,都将使用location为参数实例化一个Ship对象。

4.需求2

知道军舰在什么地方后,下面尝试移动它。首先,我们应该让它能够前进和后退。

实现让军舰前进和后退的命令(f和b)。

辅助类Location已包含方法forward和backward,它们实现了这项功能:

......
    public boolean forward() {
        return move(FORWARD, new Point(100, 100), new ArrayList<>());
    }
    public boolean forward(Point max) {
        return move(FORWARD, max, new ArrayList<>());
    }
    public boolean forward(Point max, List<Point> obstacles) {
        return move(FORWARD, max, obstacles);
    }

    public boolean backward() {
        return move(BACKWARD, new Point(100, 100), new ArrayList<>());
    }
    public boolean backward(Point max) {
        return move(BACKWARD, max, new ArrayList<>());
    }
    public boolean backward(Point max, List<Point> obstacles) {
        return move(BACKWARD, max, obstacles);
    }
......

1.规范

在军舰朝北的情况下,如果我们向前移动它,结果将如何呢?其y坐标将减1.如果军舰面向东呢?其x坐标应加1。

面对这样的情况,你的第一反应应该是编写两个类似下面的规范:

 

 

 

 

 

 

 

 

 

 

 

未完待续...

未完待续...

未完待续...

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值