对于TDD,我该如何准备数据

在开始编写一个测试之前,准备数据是一个比较头疼的问题。对于一个测试,我至少有两种方法来准备数据:

1. 创建一个带数据的文件,在before的方法中加载它

2. 创建一个builder在代码中构建一个数据的文件流或内存对象

这两种方法都可以达到我的目的,那么我该用那种方法呢?首先,我需要知道两种方法的各自优势和缺点是什么?

1. 模版数据文件,这种方法准备数据快并且简单,我们可以从实际的系统中导出一个文件用于测试,数据量可以比较多。但缺点是测试代码必须知道这个文件的位置,测试的部署比较麻烦,而且文件格式的变化会导致测试失败。如果不同测试对数据内容需求不同,就要创建新的文件来适应测试变化。

2. 动态创建数据流/内存对象,这种方法相对比较灵活,可以随意的组织数据,数据的创建过程与测试代码能更好的保持同步,并且不会受数据文件的位置影响。缺点是如果要准备大数据量,非常费力,而且速度会很慢。

所以结论是当我们的测试需要数据量小并且格式灵活的时候,我们应当用动态数据流/内存对象,通常这也是单元测试的特点。如果我们的测试需要大量固定格式的数据,那么我们应该用模版数据文件,这种特点通常是集成测试或功能测试的特点。

理论只有联系实际才能产生效果。下面以创建一个CVS读写对象来说明这个理论。

假设我要写一个CvsOperator来读写CVS文件,目的是我能通过行号和列号来获取字段内容。这个时候,我在想我是从什么地方找一个现成的cvs文件呢?还是创建一个cvs builder的内存对象。按照TDD的做法,我们应该以尽可能小的步骤前进,而一个大而全的CVS文件对我来说太复杂了。所以我创建了一个简单的CvsFileBuilder对象

    class CvsFileBuilder {
        private StringBuffer stringBuffer = new StringBuffer();

        public ByteArrayInputStream getCvsFileStream() {
            ByteArrayInputStream cvsFileStream =
                    new ByteArrayInputStream(stringBuffer.toString().getBytes());
            return cvsFileStream;
        }

        public void buildHead(String line) {
            stringBuffer.append(line+"\r\n");
        }
    }

非常的简单,就是读写流。接来了写一个测试,

    @Test
    public void should_read_head_from_cvs_file() throws IOException {
        CvsFileBuilder simpleBuilder = new CvsFileBuilder();
        simpleBuilder.buildHead("id,user_name,password");
        CvsOperator cvsOperator = new CvsOperator();
        cvsOperator.load(simpleBuilder.getCvsFileStream());
        CvsOperator.CvsHead head = cvsOperator.getHead();
        assertThat(head.getField(0), is("id"));
        assertThat(head.getField(1), is("user_name"));
        assertThat(head.getField(2), is("password"));
    }

因为这个时候的CvsOperator没有任何实现代码所以你会看到很多红的警告。这也是我们要去实现的方法。所以我就继续coding下去。

public class CvsOperator {
    private CvsHead head;

    public void load(ByteArrayInputStream cvsFileStream) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(cvsFileStream));
        head = new CvsHead(br.readLine());
    }

    public CvsHead getHead() {
        return head;
    }

    class CvsHead {

        private final String[] headFields;

        public CvsHead(String line) {
            headFields = line.split(",");
        }

        public String getField(int index) {
            return (headFields.length > index) ? headFields[index] : null;
        }
    }
}

非常快速的让测试通过,是TDD的一个原则。未完待续^_^

posted @ 2012-09-11 16:52  moonz-wu  阅读(376)  评论(0编辑  收藏  举报