TDD原理,如何让测试失败
TDD principle, how to make the test fail
其实我在研究TDD等等,我是通过例子来学习的
实际上我正在构建一个(非常非常小的)ORM 来向我介绍真正的单元测试,带有存根和模拟。
我 运行 这样,我进行了测试并做了一些小实现(getAll 方法)(失败 -> 使测试通过 -> 重构)
实际上,这是我的代码:
Mongodb 适配器
export default class MongoAdapter{
getAll(){
return new Promise((resolve, reject)=>{
resolve(['a','b','c','d']);
});
}
}
Mysql适配器
export default class MysqlAdapter{
getAll(){
return new Promise((resolve, reject)=>{
resolve(['a','b','c','d','e']);
});
}
}
工厂适配器class
import MysqlAdapter from './adapters/MysqlAdapter';
import MongoAdapter from './adapters/MongoAdapter';
export default class FactoryAdapter{
static get(name){
if(name.toLowerCase() === 'mysql') return new MysqlAdapter();
if(name.toLowerCase() === 'mongodb') return new MongoAdapter();
return null;
}
}
相关的单元测试:
TestMongoAdapter
import FactoryAdapter from '../../app/FactoryAdapter';
let chai = require('chai');
let sinon = require("sinon");
let expect = chai.expect;
/** @test {MongoAdapter} */
describe('MongoAdapter class',function(){
/** @test {MongoAdapter#getAll} */
describe('MongoAdapter#getAll',function(){
it('Expect getAll() to equals [a,b,c,d]',function(done){
let adapter = FactoryAdapter.get('mongodb');
adapter.getAll().then((value)=>{
expect(value).to.deep.equal(['a','b','c','d']);
done();
});
});
});
});
另外两个以此类推。在这种情况下,我的问题不在于语法方式。
问题
实际上,我想在相关适配器内部使用来自 MYSQL 和 MONGODB 的数据库驱动程序。实际上,我知道我应该做什么实现:在 FactoryAdapter.get
中创建 Adapter 的实例时,将驱动程序传递到 Adapter 的构造方法中
我的问题是,从那时起,我不知道在实现我的代码之前应该编写哪个测试(应该会失败)。
其实你用的其实挺多的。 :D
数据库适配器测试是集成测试,不是单元测试。您不能在与数据库分离的情况下对其进行测试...每个测试都具有相同的结构(根据 phpunit 手册),您有一个固定装置,您 运行 在固定装置上进行测试并进行断言。如果你想让测试失败,你需要写一个失败的断言。例如。你有一个 db fixture,其中包含数据,代码应该检索该数据。您编写了一个断言,它需要代码应该从数据库中检索的数据。它失败。之后,您可以处理代码。这就是数据库测试的全部内容。
如果 class 使用您的数据库适配器,那么您必须模拟适配器;创建一个假 class,你完全控制。之后,您可以注入模拟适配器而不是真实适配器,并测试 class 对其调用的方法。您可以将灯具注入模拟适配器。例如。您将 getAll returns 设置为带有一些数据的 Promise,而不是访问数据库并发送数据查询。
我看你用的是sinon。这是关于模拟 http://sinonjs.org/docs/#mocks-api .
的文档
其实我在研究TDD等等,我是通过例子来学习的
实际上我正在构建一个(非常非常小的)ORM 来向我介绍真正的单元测试,带有存根和模拟。
我 运行 这样,我进行了测试并做了一些小实现(getAll 方法)(失败 -> 使测试通过 -> 重构)
实际上,这是我的代码:
Mongodb 适配器
export default class MongoAdapter{
getAll(){
return new Promise((resolve, reject)=>{
resolve(['a','b','c','d']);
});
}
}
Mysql适配器
export default class MysqlAdapter{
getAll(){
return new Promise((resolve, reject)=>{
resolve(['a','b','c','d','e']);
});
}
}
工厂适配器class
import MysqlAdapter from './adapters/MysqlAdapter';
import MongoAdapter from './adapters/MongoAdapter';
export default class FactoryAdapter{
static get(name){
if(name.toLowerCase() === 'mysql') return new MysqlAdapter();
if(name.toLowerCase() === 'mongodb') return new MongoAdapter();
return null;
}
}
相关的单元测试:
TestMongoAdapter
import FactoryAdapter from '../../app/FactoryAdapter';
let chai = require('chai');
let sinon = require("sinon");
let expect = chai.expect;
/** @test {MongoAdapter} */
describe('MongoAdapter class',function(){
/** @test {MongoAdapter#getAll} */
describe('MongoAdapter#getAll',function(){
it('Expect getAll() to equals [a,b,c,d]',function(done){
let adapter = FactoryAdapter.get('mongodb');
adapter.getAll().then((value)=>{
expect(value).to.deep.equal(['a','b','c','d']);
done();
});
});
});
});
另外两个以此类推。在这种情况下,我的问题不在于语法方式。
问题
实际上,我想在相关适配器内部使用来自 MYSQL 和 MONGODB 的数据库驱动程序。实际上,我知道我应该做什么实现:在 FactoryAdapter.get
中创建 Adapter 的实例时,将驱动程序传递到 Adapter 的构造方法中我的问题是,从那时起,我不知道在实现我的代码之前应该编写哪个测试(应该会失败)。
其实你用的其实挺多的。 :D
数据库适配器测试是集成测试,不是单元测试。您不能在与数据库分离的情况下对其进行测试...每个测试都具有相同的结构(根据 phpunit 手册),您有一个固定装置,您 运行 在固定装置上进行测试并进行断言。如果你想让测试失败,你需要写一个失败的断言。例如。你有一个 db fixture,其中包含数据,代码应该检索该数据。您编写了一个断言,它需要代码应该从数据库中检索的数据。它失败。之后,您可以处理代码。这就是数据库测试的全部内容。
如果 class 使用您的数据库适配器,那么您必须模拟适配器;创建一个假 class,你完全控制。之后,您可以注入模拟适配器而不是真实适配器,并测试 class 对其调用的方法。您可以将灯具注入模拟适配器。例如。您将 getAll returns 设置为带有一些数据的 Promise,而不是访问数据库并发送数据查询。
我看你用的是sinon。这是关于模拟 http://sinonjs.org/docs/#mocks-api .
的文档