当设计系统是真实的来源,并且订户可以轻松自行修改代码时,代码经过充分测试就变得非常重要了。 Lindsey分享了我们如何对Sass进行单元测试以及如何进行单元测试。
在Sparkbox社区,我们非常熟悉和喜爱设计系统,特别是当这些系统出色完成了任务,而且不断地得到改进。优秀的设计系统都是被接受和期待的,且具有巨大的潜在价值的。
作为团队的一员,我最近正为一个企业客户构想,设计,建立以及持续优化一个设计系统。这个特殊的设计系统分布在多个产品当中,是我们这两年半来一直在迭代的产品。它已经被少数几个我们称作“订阅者”的用户所接受。由于我们的设计系统是所有公司众多品牌和在线渠道中风格的“真实来源”,因此我们投入系统的样式的准确性非常重要。例如,如果我们要进行更新,但是这个更新破坏了订阅者的风格,则可能会影响生产代码。 这将导致我们的设计系统不信任,并可能影响我们为订户提供良好服务的能力受到质疑。
我们知道我们的企业客户的设计系统需要始终可靠,我们会非常认真地对其进行任何更新。最近,订阅者要求我们提供Sass
的mixins
和functions
两个函数,用于测试颜色,排版和间距等功能。其实这些东西已经存在的了,但是由于订阅者是无法进入我们的代码库,所以他们是用不了这些功能的。因此我们需要把我们的代码做得更加通用,但是如果这些更改操作不正当的话,将会对我们的底层代码有具大的影响。我们从不希望订阅者担心我们所做的更改会破坏他们的代码,因此我们开始研究如何对Sass进行单元测试。
一、什么是单元测试?
“你应该对你的sass代码进行单元测试吗?”这是一个很好的问题。然而,”你为什么想要这样做?”无疑是一个更好的问题。
确保你的代码都正确编译
用到sass的mixins
和function
的项目在单元测试中获益很大,因为其的确保证了你的代码的编译正确性。如果你的项目总体上都不怎么用到sass
、mixins
和function
,那么单元测试对你来说没啥用。mixins
和function
是sass的两个非常强大的特性,但是对于检查这些输出的准确性,sass就不那么好处理了。你的css可能依然可以正常编译,但是输出却不一定是我们所预期的。就我们的设计系统而言,以我们改变某些sass文件为例,这些例子当中,可能会改变级联并影响有关颜色或字体的编译样式。
快速捕获输出错误
对Sass进行单元测试的另一个原因是因为Sass是可以可变的库。这就会影响我们的css输出,这些我们都不可能立即发现的。进行单元测试将有助于在我们的代码发送到生产之前捕获输出错误,并允许我们在库更改时更快地调试这些错误。
对于我们当前的项目,我们使用一个名为True、由Miriam Suzanne开发,用于进行单元测试的开源工具。该工具目前维护良好,有多种方法可将其集成到您的项目中。
二、如何使用True工具?
有不少方法可以实现True,但下面的这些设置说明均来自True文档网站上的“使用Mocha
(或其他JS Test Runners
)”。这些说明假设您在项目中设置了npm
和node-sass
。
首先,用npm安装True:
npm install sass-true
设置测试文件结构的方式完全取决于你自己。但是,如果您已经使用Sass partials
来组织项目的样式,我建议您以类似的方式设置测试。您的单元测试是用Sass编写的,因此您可以使用partials来组织文件。下面是我们如何将我们的单元测试与Jasmine测试和设置文件一起组织的示例:
然后,将True导入项目(您的文件路径可能不同)并指定要测试的Sass文件:sass-tests.scss
// sass-tests.scss
@import "node_modules/sass-true/sass/true";
@import "../../../my-styles.scss";
接下来,您将编写用于设置Sass测试的JavaScript文件。我将依据Describe / It
测试模式进行测试。Describe / It
测试模式提供了测试结构,使测试的输出易于理解。
新建一个js测试文件:true-sass-spec.js
//true-sass-spec.js
var path = require('path');
var sassTrue = require('sass-true');
var sassFile = path.join(__dirname, 'true-sass-tests/sass_tests.scss');
sassTrue.runSass({file: sassFile}, describe, it);
现在你进行到了最有趣的一步——为我们的sass代码编写单元测试条件。
编写测试条件有两种主要方法,具体取决于您是在测试function
还是mixin
。我将从一个测试mixin
的例子开始。
这是mixin
在你的Sass中的样子:
@mixin primary-header {
font-family: "Helvetica", Arial, sans-serif;
font-size: 2rem;
line-height: 2.5rem;
color: #333;
text-decoration: underline;
}
以下是对它的测试:
// Describe what you're testing
@include describe('The primary-header mixin') {
// Explain what it should do
@include it('outputs the properties of our primary header.') {
// Assert the output of the mixin matches the expected result
@include assert {
@include output {
@include primary-header();
}
@include expect {
font-family: "Helvetica", Arial, sans-serif;
font-size: 2rem;
line-height: 2.5rem;
color: #333;
text-decoration: underline;
}
}
}
}
当此测试通过时,以下是它在控制台console
中的大概样子:
请注意,这些输出读起来就像正是发生了什么的句子。这是故意的,是通过使用Describe / It
模式来完成的。
您还可以在上面的代码中使用contains
而不是expect
来测试子集是否存在某个属性。如果输出中有很多属性,但是并不需要测试所有属性,这样做则会减少大量代码,非常有用。更多的方法在True website上有说明。
这是我们想测试的Sass的function
的一个例子:
@function divide-height ($height) {
$startingHeight: 100%;
@return $startingHeight / $height;
}
以下是对它的测试:
// Describe the function
@include describe('The `divide-height` function') {
// Describe what it should do
@include it('returns a valid height when given valid input.') {
// Test your function with an input
$test: divide-height('2');
// What the expected value should be
$expect: 50%;
// Assert they are equal, otherwise show the error message
@include assert-equal($test, $expect, "The height is either incorrect or does not exist.");
}
}
控制台将输出失败,因为我们传递给我们的function(2)
的输入是一个字符串,而不是一个数字,因此导致失败。
如果传递了正确输入的测试:
// Describe the function
@include describe('The `divide-height` function') {
// Describe what it should do
@include it('returns a valid height when given valid input.') {
// Test your function with an input
$test: divide-height(2);
// What the expected value should be
$expect: 50%;
// Assert they are equal, otherwise show the error message
@include assert-equal($test, $expect, "The height is either incorrect or does not exist.");
}
}
则会通过测试:
三、先写一个不能通过的测试
感谢Sparkboxer Catherine的提醒,我最近在编写单元测试时学到的一个技巧是,你想先将测试编写为失败,然后调整它们以使它们通过。如果您的测试在您编写后立即通过,那么它们实际上可能无法正常工作。我们最近在测试一个无法正常工作的mixin
时遇到了这种情况。结果是mixin
和test
都没有返回任何输出,但测试没有失败,因为它们相等了(都没有输出)。如果我们先把测试写成失败,我们会更早地发现这个问题。
四、测试更多,担心更少
设计系统,web apps
或任何在Sass中使用mixin
或function
的项目都可以从单元测试中获益,以确保代码按预期进行编译。您可以及时发现可能会被忽视的意外输出。如果你确信你的测试会发现潜在的错误,那么在重构时你也会少担心。Sass单元测试是您可以添加到您的武器库中以确保正确构建Web的一件事。
原文:How and Why We Unit Test Our Sass ——LINDSEY WILD(06-25-18)