sass框架
So you’ve written (or want to write) an awesome Sass toolkit, framework, or even a small function or mixin, and you want to share it with the world. Fantastic! That’s what’s great about open-source software development — you get to collaborate on code with other supportive developers in the community to create useful software that many can benefit from.
因此,您已经编写了(或想要编写)一个很棒的Sass工具箱,框架,甚至是一个小的函数或mixin,并希望与世界分享。 太棒了! 这就是开源软件开发的优点-您可以与社区中其他支持开发人员就代码进行协作,以创建许多人都可以从中受益的有用软件。
But, not so fast! It’s very important to test your software before releasing it. One of the most efficient ways to do this is with unit tests, which are automated scripts that test if a single function of a single unit of code behaves according to a defined specification.
但是,没有那么快! 在发布软件之前测试软件非常重要。 最有效的方法之一是使用单元测试 ,它是自动脚本,用于测试单个代码单元的单个功能是否按照定义的规范运行。
Sass gives you the ability to manipulate data using functions, operators, variables, and control directives and expressions. The return value of a @function can also be tested directly against the expected value. For CSS output and visual regression testing, a tool like PhantomCSS is better suited for the job, though @mixins can be tested in the latest version of True.
Sass使您能够使用函数 , 运算符 , 变量以及控制指令和表达式来操纵数据。 @function的返回值也可以直接与期望值进行测试。 对于CSS输出和视觉回归测试,就像一个工具PhantomCSS更适合这份工作,虽然@mixins可以在真正的最新版本进行测试。
We will be using Eric Suzanne’s True testing framework for unit testing sample functions in Sass, but the guidelines presented are applicable for any Sass testing framework. For simple tests, you might want to use a minimalistic (and awesome) Sass testing framework such as Hugo Giraudel’s SassyTester.
我们将使用Eric Suzanne的True测试框架对Sass中的示例函数进行单元测试,但是所提供的准则适用于任何Sass测试框架。 对于简单的测试,您可能需要使用简约(且功能强大)的Sass测试框架,例如Hugo Giraudel的SassyTester 。
True can be installed as a Ruby gem (gem install true) or a Bower package (bower install true). Configuration options can be found in True’s documentation. From there, a load path can be setup to point to the True installation.
True可以作为Ruby gem( gem install true )或Bower软件包( bower install true ) bower install true 。 可以在True的文档中找到配置选项。 从那里,可以设置加载路径以指向True安装。
Keep test files in a separate directory from your Sass files. This is so that tests can be easily .gitignore-d and exempt from accidental Sass watching and compiling. If a project is mainly a Sass project, the directory can simply be named /tests, with the main test file located at /tests/tests.scss.
将测试文件与Sass文件放在单独的目录中。 这样一来,测试就可以轻松地.gitignore -d并免于意外的Sass监视和编译。 如果项目主要是Sass项目,则目录可以简单地命名为/tests ,而主测试文件位于/tests/tests.scss 。
Inside the /tests directory, it helps to organize your tests by module, which is usually by the @function or @mixin it represents. Sometimes, similar functions and mixins can be grouped in the same module.
在/tests目录中,它有助于按模块组织测试 ,该模块通常由其代表的@function或@mixin来组织 。 有时,相似的功能和混合可以组合在同一模块中。
// Sample Sass project structure /css /scss /tests /api _foo.scss _bar.scss _all.scss // imports foo and bar tests /helpers _baz.scss _qux.scss _all.scss // imports baz and qux tests tests.scss // imports api/_all and helpers/_all index.html package.json // ... etc.The main test file, tests.scss, will be responsible for importing and reporting all of the tests and the actual SCSS project that will be tested:
主测试文件tests.scss将负责导入和报告所有测试以及将要测试的实际SCSS项目:
@import 'true'; // Import the project @import '../scss/project'; // Import the test files @import 'api/all'; @import 'helpers/all'; // Run the tests @include report();In order to effectively unit test functions, it’s best to collect the specifications of the function being tested. In a modular architecture, each function has a single responsibility — it has one job, and usually returns the same type of value.
为了有效地对功能进行单元测试,最好收集要测试的功能的规范。 在模块化体系结构中,每个功能都有一个职责 -它有一项工作,通常返回相同类型的值。
A simple way to create specifications for a function is by saying that “it should (do something)” given a certain input. This is a tenet of behavior-driven development, which can be seen in other testing frameworks such as Jasmine (JavaScript).
创建功能规范的一种简单方法是,在给出特定输入的情况下说“ 它应该(做某事) ”。 这是行为驱动开发的宗旨,可以在其他测试框架(例如Jasmine(JavaScript))中看到。
Let’s take a look at an example function (and relevant variables):
让我们看一个示例函数(和相关变量):
// inside 'scss/project.scss' $type-base-font-size: 16px !default; $type-base-ratio: 1.4 !default; @function type-scale( $exponent: 1, $base: $type-base-font-size, $ratio: $type-base-ratio, $factor: 1 ) { @return ceil(($factor * $base) * pow($ratio, $exponent)); }This is a very simple function that should return the appropriate font size based on the modular scale (see type-scale.com for a visual representation of this concept). With this, we have our first spec:
这是一个非常简单的函数, 应该根据模块化比例返回适当的字体大小 (有关此概念的直观表示,请参见type-scale.com )。 有了这个,我们有了第一个规格 :
// inside 'tests/api/type-scale.scss' @include test-module('type-scale') { @include test('should return the appropriate font size based on the modular scale') { $actual: type-scale(1); $expected: 23px; // based on base 16px and ratio 1.4 @include assert-equal($actual, $expected); } }There are three main parts here:
这里有三个主要部分:
test-module: the module (or unit) of code that you are testing; in this case, the type-scale function
test-module :您正在测试的代码模块(或单元 ); 在这种情况下, type-scale函数
test: a specification or assumption about the unit being tested
测试 :关于被测单元的规格或假设
assertion: the assertion that the actual value meets the expected value.
断言 :实际值符合期望值的断言 。
To make tests easier to manage, my preference is to store the $actual and $expected values in variables before testing the assertion. In True, there are four types of assertions:
为了使测试更易于管理,我的首选是在测试断言之前将$actual和$expected值存储在变量中 。 实际上,有四种类型的断言:
assert-true($value) asserts that the value is truthy
assert-true($value)断言该值是真实的
assert-false($value) asserts that the value is not truthy, e.g. null or false
assert-false($value)断言该值不真实 ,例如null或false
assert-equal($assert, $expected) asserts that the actual (asserted) and expected values are equal
assert-equal($assert, $expected)断言实际(确定)值和期望值相等
assert-unequal($assert, $expected) asserts that the actual (asserted) and (un)expected values are not equal
assert-unequal($assert, $expected)断言实际(声明)和(未)期望值不相等
Let’s go over a few strategies for unit testing functions.
我们来看一下单元测试功能的一些策略。
In our above function, we’re assuming that the global variables $type-base-font-size == 16px and $type-base-ratio == 1.4. Assumptions are dangerous in testing, as is mutable data. Set up a @mixin that can enforce these values before each test:
在上面的函数中,我们假设全局变量$type-base-font-size == 16px和$type-base-ratio == 1.4 。 假设和可变数据一样,在测试中也很危险。 设置一个@mixin ,可以在每次测试之前强制执行这些值:
@mixin test-type-scale-before() { $type-base-font-size: 16px !global; $type-base-ratio: 1.4 !global; }Now, these variables will be safe from outside modifications in every test that includes this @mixin:
现在,在包含此@mixin每个测试中,这些变量都不受外部修改的@mixin :
@include test-module('type-scale function') { @include test('...') { @include test-type-scale-before(); // ... test code } }A Sass @function can include many arguments (though it’s best to limit these), and it’s a good idea to test each one individually to ensure that they return the expected result:
Sass @function可以包含许多参数(尽管最好限制这些参数),并且最好单独测试每个参数以确保它们返回预期的结果:
@include test('should work with an integer $exponent') { @include test-type-scale-before(); $actual: type-scale($exponent: 2); $expected: 32px; @include assert-equal($actual, $expected); } @include test('should work with a negative integer $exponent') { @include test-type-scale-before(); $actual: type-scale($exponent: -2); $expected: 9px; @include assert-equal($actual, $expected); } @include test('should work with a numerical font $base') { @include test-type-scale-before(); $actual: type-scale($exponent: 2, $base: 10px); $expected: 20px; @include assert-equal($actual, $expected); } // ... etc. for $ratio, $factorOf course, if your function has default arguments, an assertion should be made that the function, when called with no arguments, returns the expected result.
当然,如果您的函数具有默认参数,则应断言该函数在不带参数的情况下返回预期的结果。
@include test('should return the base font size with default arguments') { @include test-type-scale-before(); $actual: type-scale(); $expected: $type-base-font-size; @include assert-equal($actual, $expected); }Sometimes, an argument can accept either different types of values, or values with different units. Use the @each, @while, or @for directives to iterate through all potential values the arguments can accept:
有时,参数可以接受不同类型的值或具有不同单位的值。 使用@each , @while或@for指令遍历参数可以接受的所有可能值:
@include test('should work with different units for $base') { @include test-type-scale-before(); $values: (10px, 100%, 10pt); // etc. $units: ('px', 'percent', 'pt'); // etc. $expected-values: (14px, 140%, 14pt); // etc. @for $index from 1 through length($values) { $value: nth($values, $index); $unit: nth($units, $index); $actual-value: type-scale(1, $value); $expected-value: nth($expected-values, $index); @include assert-equal($actual-value, $expected-value, 'Works with #{$unit}'); } }With True, a @mixin can be tested for correctness by comparing the actual output to the expected output. The syntax is similar to the function assertions, with the addition of an @include input and @include expect mixin.
使用True,可以通过将实际输出与预期输出进行比较来测试@mixin的正确性。 语法类似于函数断言,不同之处在于添加了@include input和@include expect mixin。
Here is an example type-scale mixin that uses the type-scale() function:
这是一个使用type-scale()函数的示例类型比例混合:
@mixin type-scale($exponent: 0) { font-size: type-scale($exponent); }And here is its accompanying test:
这是它的伴随测试:
@include test('@mixin type-scale()') { @include assert('should output the appropriate font size') { @include input { @include type-scale(1); } @include expect { font-size: 23px; } } }Now, when the tests are run, you can compare the .input { ... } block to the .expect { ... } block for this test:
现在,在运行测试时,可以将此测试的.input { ... }块与.expect { ... }块进行比较:
/* @mixin type-scale() */ [data-module="type-scale function"] [data-test="@mixin type-scale()"] [data-assert="should output the appropriate font size"] .input { font-size: 23px; } [data-module="type-scale function"] [data-test="@mixin type-scale()"] [data-assert="should output the appropriate font size"] .expect { font-size: 23px; }The guidelines for testing mixins should be the same as those for testing functions. Make sure to test every argument, default values, and iterate through different potential values.
测试mixin的准则应与测试功能的准则相同。 确保测试每个参数,默认值,并遍历不同的潜在值。
To make mixins easily testable, separate logic out of mixins and into functions. Functions are directly testable, and this will provide greater modularity and separation of concerns inside your project.
为了使mixin易于测试,请将逻辑从mixins中分离出来并分解为功能。 功能是直接可测试的,这将提供更大的模块化和项目内部关注点的分离。
With True, there are a couple ways to run the tests – via true-cli in the terminal, or with node-sass and your test runner of choice, such as MochaJS. Refer to True’s documentation for more information on setting up and running tests. If you are using the terminal, it’s as simple as running true-cli path/to/your/tests.scss.
使用True,可以通过多种方式运行测试-通过终端中的true-cli或通过node-sass和您选择的测试运行器(例如MochaJS)运行 。 有关设置和运行测试的更多信息,请参阅True的文档 。 如果您使用的是终端,则就像运行true-cli path/to/your/tests.scss一样简单。
All of the above tests inside @include test() should be inside an @include test-module(), with the name of the specific unit you are testing as the name of the module, such as @include test-module('type-scale'). You can check out this Sassmeister gist to see all the above tests in action.
@include test()内的所有上述测试均应在@include test-module() ,将要测试的特定单元的名称作为模块的名称,例如@include test-module('type-scale') 。 您可以查看此Sassmeister要点,以查看上述所有测试。
Unit tests can save you hours of development time by automating the process of testing every part of your project. That way, you can refactor with the reassurance that, if all of the unit tests pass, the code can be safely used and is correctly implemented. Unit testing naturally emphasizes a modular project structure, as well.
单元测试通过自动化测试项目每个部分的过程,可以节省您的开发时间。 这样,您可以放心重构,如果所有单元测试都通过了,则可以安全地使用并正确执行代码。 单元测试自然也强调模块化项目结构。
A good rule of thumb: less code is better, and more unit tests are better. Keep the scope and responsibilities of your project’s units (mixins and functions) small, and they will be easily testable. Test for every possible input, and ensure that your functions are as idempotent as possible.
有一个很好的经验法则:代码越少越好,而单元测试越多越好。 保持项目单元(混合单元和功能)的范围和职责较小,并且易于测试。 测试所有可能的输入,并确保您的功能尽可能幂等 。
If you want to see some real-life usage of unit tests in a Sass library, check out the unit tests I’ve written for Sassdash. Happy testing!
如果您想在Sass库中看到真实的单元测试用法,请查看我为Sassdash编写的单元测试。 测试愉快!
翻译自: https://www.sitepoint.com/creating-tests-sass-framework/
sass框架
相关资源:金融计算与建模,SASS教程