use*_*472 23 unit-testing d3.js
我是D3JS的新手,想了解D3 JS的测试策略.
要详细说明问题 - 请考虑我有一个简单的页面,显示使用TSV文件的折线图.
Java脚本代码:
function LineManager() {}
function LineProperties() { // Line Properties }
LineManager.prototype.draw = function(properties) {
// D3 code to draw a line with the given properties.
}
Run Code Online (Sandbox Code Playgroud)
我无法考虑编写单元测试时要考虑的测试用例.这是我写的一个示例测试..
it("should throw an exception if line graph properties are not set.", function() {
expect(lineManager.draw.bind(lineManager)).toThrow("Line Graph properties not set");
});
it("It should have single line chart", function() {
lineManager.draw(properties);
expect(lineManager.countLines()).toEqual(1);
});
Run Code Online (Sandbox Code Playgroud)
我已编写单元测试以确保正确生成TSV文件.但编写单元测试以查看数据是否正确呈现是否有意义?这不是更多的d3js单元测试而不是单元测试我的功能吗?
所以我的问题是 - 对于由d3js生成的图表应该考虑哪些测试?
use*_*472 10
我想我得到了自己问题的答案.将试着在这里解释一下.
使用D3JS编写的JS函数无法验证图形是否正确绘制.为此,我们可能必须使用Phantom.js或Chrisopher提到的类似框架.我并不担心确保D3JS正确绘制图形,因为任何方式都是D3JS功能,我的代码可以安全地假设D3JS正在进行其工作.
我担心的是传递给D3JS的数据是否正确并且符合我的要求.通过创建Spy对象,可以确保正确设置图形的属性.我正在提供一个样本单元测试,涵盖使用D3JS绘制圆形的JS代码的测试用例.
CircleManager.js
function CircleManager() {};
CircleManager.prototype.draw = function(radius) {
var svg = d3.select("body")
.append("svg");
svg.attr("width", 100)
.attr("height", 100);
var circle = svg.append("circle");
circle.style("stroke", "black")
.style("fill", "white")
.attr("r", radius)
.attr("cx", 50)
.attr("cy", 50);
};
Run Code Online (Sandbox Code Playgroud)
CircleManagerSpec.js
describe("draw", function() {
it("Constructs an svg", function() {
var d3SpyObject = jasmine.createSpyObj(d3, ['append', 'attr']);
// Returns d3SpyObject when d3.select method is called
spyOn(d3, 'select').andReturn(d3SpyObject);
var svgSpyObject = jasmine.createSpyObj('svg', ['append', 'attr', 'style']);
// Returns svgSpyObject when d3.select.append is called.
d3SpyObject.append.andReturn(svgSpyObject);
d3SpyObject.attr.andCallFake(function(key, value) {
return this;
});
svgSpyObject.append.andReturn(svgSpyObject);
svgSpyObject.attr.andCallFake(function(key, value) {
return this;
});
svgSpyObject.style.andCallFake(function(key, value) {
return this;
});
var circleManager = new CircleManager();
circleManager.draw(50);
expect(d3.select).toHaveBeenCalledWith('body');
expect(d3SpyObject.append).toHaveBeenCalledWith('svg');
expect(svgSpyObject.attr).toHaveBeenCalledWith('r', 50);
expect(svgSpyObject.attr).toHaveBeenCalledWith('width', 100);
expect(svgSpyObject.attr).toHaveBeenCalledWith('height', 100);
expect(svgSpyObject.style).toHaveBeenCalledWith('stroke', 'black');
expect(svgSpyObject.style).toHaveBeenCalledWith('fill', 'white');
});
});
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.
测试策略
我最终用来测试d3.js代码的策略是创建辅助函数来管理我的数据和设置.然后我对这些功能进行单元测试 因此,对于图表,我会检查处理数据的每个功能,每个功能设置宽度,图例等...
关于绘图函数,它可能会变得更加棘手,但是使用诸如buster.js之类的测试框架也可以非常容易地实现它们.测试图表的一种好方法是计算页面中条形图/线条的数量,检查图例是否打印等.
我不会尝试检查图表在视觉上是否相同,因为直观地检查最终结果是否相同是最简单的.但是,在编写绘图函数时,应该非常关注更新时发生的事情(将数据绘制的数量改为两倍?选择器是否正确?...)
Javascript测试
一本关于javascript测试的好书是:测试驱动的Javascript开发.它提供了许多测试javascript代码的示例和策略.其中大多数可以直接应用于d3.js代码.
工具
我最近寻找单元测试d3.js代码的解决方案,最后我使用了以下工具:
buster.js
Buster.js是一个非常完整的框架,用于在多个浏览器中对javascript代码进行单元测试.
phantom.js
Phantom.js是一个带有JavaScript API的无头WebKit脚本.
这意味着它可以轻松地在javascript上运行自动化测试,而无需使用chrome,safari等浏览器.
编辑:我现在将使用茉莉花进行单元测试和硒(通过Saucelabs服务)进行端到端测试.
我想你应该考虑一下:http://busypeoples.github.io/post/testing-d3-with-jasmine/
它似乎有道理.我已经阅读了其他人的答案,但我对他们有点不同意.我认为我们不仅要检查是否调用了正确的函数,而且我们可以检查更多.仅检查一些函数调用是否适合单元测试级别但不够.开发人员编写的这些测试用例将基于开发人员的理解,就像调用或不调用这些函数一样.但是,无论是否应该调用这些方法,只能通过另一个级别来检查这个东西,因为与其他工作不同,这里的代码是使某些东西不能返回可以被检查的东西并确保一切正确.
我们显然不需要检查D3是否正常工作.所以我们可以在测试代码中使用D3.但D3渲染SVG,我们可以检查svg是否有预期的元素.同样,它不会测试SVG是否正在显示和正确呈现.我们将检查SVG是否具有预期的元素,并且它们是按预期设置的.
例如:如果这是条形图,我们可以检查条形数.如上面链接中的示例所示,检查一下.
// extend beforeEach to load the correct data...
beforeEach(function() {
var testData = [{ date: '2014-01', value: 100}, { date: '2014-02', value: 140}, {date: '2014-03', value: 215}];
c = barChart();
c.setData(testData);
c.render();
});
describe('create bars' ,function() {
it('should render the correct number of bars', function() {
expect(getBars().length).toBe(3);
});
it('should render the bars with correct height', function() {
expect(d3.select(getBars()[0]).attr('height')).toBeCloseTo(420);
});
it('should render the bars with correct x', function() {
expect(d3.select(getBars()[0]).attr('x')).toBeCloseTo(9);
});
it('should render the bars with correct y', function() {
expect(d3.select(getBars()[0]).attr('y')).toBeCloseTo(0);
});
});
// added a simple helper method for finding the bars..
function getBars() {
return d3.selectAll('rect.bar')[0];
}
Run Code Online (Sandbox Code Playgroud)
有些人可能会说我们将在测试代码中使用D3?我们应该再次记住,这里测试编写的目的不是测试D3,而是我们的逻辑和SVG代码,它是为响应我们的代码而编译的.
这只是一种方式,茉莉花是帮助我们编写测试的东西,您还可以在不同的场景中进行更详细的介绍.您可以创建域并检查数据点宽度高度以交叉检查它们是否会导致渲染的数据.
我想我很清楚,如果没有那么检查这个链接:http://busypeoples.github.io/post/testing-d3-with-jasmine/
在这里写这篇文章已经详细解释了如何使用茉莉花.另外我觉得我还是详细了.如果在不同的js函数级别只需要进行单元测试,那么还有很多东西可以在不进入元素细节的情况下进行测试.