最初出版的here
介绍
我想您可能正在使用Elasticsearch或计划,因为您已经打开了本文ð另一个假设 - 您肯定会发现通过某些集成测试锁定功能是一个好主意。真的是!
当前工作的公司拥有90%以上的代码覆盖范围,并具有集成测试!我建议每个人都通过测试覆盖他们的代码库,因为正如一个智者所说:
[没有单位测试]您不进行重构,您只是更改狗屎。
hamletdâarcy
设置
想象一下,您有一台简单的RESTFUL服务器,其中包含一些使用Elasticsearch的逻辑。在当前的展示柜中。
const Hapi = require('@hapi/hapi');
const Qs = require('qs');
const {createHandler} = require("./create/index.js");
const {readAllHandler, readHandler} = require("./read/index.js");
const {updateHandler} = require("./update/index.js");
const {deleteAllHandler, deleteHandler} = require("./delete/index.js");
const init = async () => {
const server = Hapi.server({
port: 3000,
host: 'localhost',
query: {
parser: (query) => Qs.parse(query)
}
});
server.route({
method: 'POST',
path: '/',
handler: createHandler
});
server.route({
method: 'GET',
path: '/{id}',
handler: readHandler
});
server.route({
method: 'GET',
path: '/',
handler: readAllHandler
});
server.route({
method: 'PATCH',
path: '/{id}',
handler: updateHandler
});
server.route({
method: 'DELETE',
path: '/{id}',
handler: deleteHandler
});
server.route({
method: 'DELETE',
path: '/',
handler: deleteAllHandler
});
await server.start();
server.events.on('log', (event, tags) => {
console.log({event}, {tags})
if (tags.error) {
console.log(`Server error: ${event.error ? event.error.message : 'unknown'}`);
}
});
console.log('Server running on %s', server.info.uri);
};
process.on('unhandledRejection', (err) => {
console.log(err);
process.exit(1);
});
init();
现在,您需要使用一些测试来涵盖每条路线的逻辑,以锁定功能并防止商业逻辑被打破。
一个明显但并不简单的解决方案是每次都使用Docker并旋转弹性进行测试。
但是,值得吗?我的意思是您真的想在管道环境中有更长的时间?也许已经有解决方案了?
此插件下载并在开玩笑开始时,请下载和缓存弹性搜索二进制文件,然后插件自动在定义的端口上启动弹性,并在完成测试后将其撕下。
如何添加测试?
我有一个在pull request中设置有/没有开玩笑测试的示例,因此您可以比较所有更改。但是现在让我们逐步通过它。
1.安装其他模块
yarn add --dev jest @shelf/jest-elasticsearch @types/jest
2.添加Jest-config.js
touch jest.config.js
module.exports = {
preset: '@shelf/jest-elasticsearch',
clearMocks: true,
collectCoverage: true,
coverageDirectory: "coverage",
coverageProvider: "v8"
};
另外,您可以使用CLI tool自行生成Jest Config。
3.为插件添加jest-es-config.js
touch jest-es-config.js
const {index} = require('./src/elastic.js');
module.exports = () => {
return {
esVersion: '8.4.0',
clusterName: 'things-cluster',
nodeName: 'things-node',
port: 9200,
indexes: [
{
name: index,
body: {
settings: {
number_of_shards: '1',
number_of_replicas: '1'
},
mappings: {
dynamic: false,
properties: {
id: {
type: 'keyword'
},
value: {
type: 'integer'
},
type: {
type: 'keyword'
},
name: {
type: 'keyword'
},
}
}
}
}
]
};
};
4.扩展软件包。JSON脚本进行测试
{
"scripts": {
"test": "jest"
"serve": "node src/index.js"
}
}
5.调整弹性客户端
const dotenv = require('dotenv')
dotenv.config()
const {Client} = require('@elastic/elasticsearch');
module.exports.client = new Client({
node: process.env.NODE_ENV === 'test' ? 'http://localhost:9200' : process.env.ES_URL
})
module.exports.index = 'things'
添加一个条件,每当我们运行测试时,都会使用node_env连接到本地旋转的弹性。
利润!
现在所有的东西都准备好编写和运行测试。所有路线都在这里完全覆盖并存储:
elastic-jest-example
作为示例,让封面创建功能业务逻辑。
const {ulid} = require('ulid');
const {client, index} = require("../elastic.js");
module.exports.createHandler = async (request, h) => {
if (Object.keys(request.payload))
try {
const res = await this.create(request.payload)
return h.response(res).code(200);
} catch (e) {
console.log({e})
return h.response({e}).code(400);
}
}
// let's cover this function with some tests
module.exports.create = async (entity) => {
const {
type,
value,
name,
} = entity;
const document = {
id: ulid(),
type: type.trim().toLowerCase(),
value: +value.toFixed(0),
name: name.trim()
}
await client.index({
index,
document
});
return document.id
}
创建一个测试文件并添加几个语句。
touch src/create/index.test.js
const {create} = require("./index.js");
const {client, index} = require("../elastic");
describe('#create', () => {
// clear elastic every time before running it the statement.
// It's really important since each test would be idempotent.
beforeEach(async () => {
await client.deleteByQuery({
index,
query: {
match_all: {}
}
})
await client.indices.refresh({index})
})
it('should insert data', async () => {
expect.assertions(3);
const res = await create({type: 'some', value: 100, name: 'jacket'})
await client.indices.refresh();
const data = await client.search({
index,
query: {
match: {
"id": res
}
}
})
expect(res).toEqual(expect.any(String))
expect(res).toHaveLength(26);
expect(data.hits.hits[0]._source).toEqual({
"id": res,
"name": "jacket",
"type": "some",
"value": 100
}
);
})
it('should insert and process the inserted fields', async () => {
const res = await create({type: 'UPPERCASE', value: 25.99, name: ' spaces '})
await client.indices.refresh();
const data = await client.search({
index,
query: {
match: {
"id": res
}
}
})
expect(data.hits.hits[0]._source).toEqual({
"id": res,
"name": "spaces",
"type": "uppercase",
"value": 26
}
);
})
});
可以简单地描述每个业务逻辑功能的基本测试流:
插入数据 - >运行测试的功能 - >检查输出 - >清除数据 - >重复
数据插入/删除可以通过将其统一为助手并使用其他mooching libs来改进。
弹性拆卸由@shelf/jest-elasticsearch lib本身管理。
遵循的另一个好惯例是覆盖您正在使用DorcidentBlock测试的每个功能,因此以后您可以轻松地使用IDE助手进行特定的测试,而无需重新整体套件:
资源
现在您知道如何使用开玩笑测试弹性搜索查询。
jest-elasticsearch
另外,您有一个小的蓝图存储库,并准备使用设置!
elastic-jest-example
希望本文能够帮助您设置并测试弹性项目!
想连接吗?
在Twitter上关注我!
阅读更多:
How to update 63 million records in MongoDB 50% faster?
Optimizing massive MongoDB inserts, load 50 million records faster by 33%!