Hello, my name is Monica Kozbial and I’m going to be talking about
the test helpers provided by the @blockly/dev-tools plugin.
One of the plugins that we publish on npm is @blockly/dev-tools. It provides a few different
features, and one of them is test helpers that you can use in your automated mocha tests.
These helpers contain a lot specialized functions for testing Blockly Blocks and FIelds,
and that's what I'm going to be going over in this talk. I’ll start with briefly talking
about what you’d want to test for Blocks and Fields, then I'll go over Field test helpers,
then Block test helpers, and finally some generic common test helpers.
These helpers were designed to make it easier to write tests for Blocks and Fields
for a lot of test cases, without needing to use a lot of code.
If you’ve written any, or plan to write any, custom Blocks or Fields,
this talk will be helpful in letting you know what's available for you to use.
We'll include links below this video to the source code for the helpers covered in this talk.
What to test? For any Block or Field, there's a few common things that you should test.
For Fields, you should test the constructor,
the deserialization of the field, through the fromJson method, setValue, and the validators.
For Blocks, you should test creation, code generation and serialization.
Now let's get into the test helpers we provide for field tests.
In the test helpers, there are specialized helpers
written for running constructor, fromJson, and setValue field tests.
Additionally, there is a general purpose helper function called assertFieldValue
provided for asserting a fields value that should work for most fields.
It compares the values returned from getValue and getText
for the provided field, against the expected values passed in.
The helper provided for running constructor tests is runConstructorSuiteTests.
It generates a mocha test suite with the title "Constructor" and creates mocha tests that test
that your field behaves correctly when it's passed valid and invalid values through its constructor.
For valid arguments it checks that the field is set to the past value and no errors are thrown.
For invalid arguments it checks that the field is either set to an expected default value
or that an error is thrown. With this function you should be able to find
multiple valid and invalid test cases easily and cover a lot of different edge cases.
Here's a code sample of what it looks like to use this helper function.
You can easily configure multiple tests by either defining it as an invalid or valid test case
of the type FIeldCreationTestCase and passing it into the call for runConstructorSuiteTests.
This method takes the invalid and valid test cases, an assertion method to check the field
state after its passed valid arguments, and optionally an assertion method that checks
that the field is set to a default value called for invalid value test cases. If the
assertFieldDefault method is not passed then it's assumed that the field is expected to throw on
invalid arguments rather than be set to a default value. You can check the JSDoc for field creation
test case type in Blockly Samples to learn further about how the test case can be configured.
Similar to run constructor suite tests, run from json suite tests should reduce the amount
of code needed to set up fromJson tests. It generates a mocha test suite titled "fromJson"
and takes in the same parameters as runConstructorSuiteTests. The difference between
this method and the runConstructorSuiteTests method is that this test covers creating the field
using the fromJson method while the ladder is testing creation through the fields constructor.
Here's a code sample for runFromJsonSuite tests. The configuration for all the parameters is
exactly the same and it's generally expected that your constructor and fromJson method
handle invalid and valid values the same, so you should expect to be able to reuse the same
parameters for this call which further simplifies what you need to do to write these tests.
The helper provided for running set value tests is runSetValueTests. It tests the behavior of
the field when the setValue call on it is past valid and invalid values.
For valid values it checks the field has the expected value and text. For invalid values it
checks the field has the expected fallback value and text. Unlike the previous two helpers the
runSetValueTests method doesn't generate a mocha test suite that wraps the generated mocha tests.
You are responsible for creating the test suite to wrap these tests as well as a
mocha setup function that instantiates the field on this.field with an initial value.
You can call this function multiple times with test suites with fields with different
initial values to cover more edge cases. We do this for the boolean field in core.
Here's a code sample for runSetValueTests. The valid and invalid test cases that are
passed to runSetValueTests are of the type fieldValueTestCase, which is a super type
of fieldCreationTestCase. You can often reuse the valid and invalid test case configuration
that's passed for the runConstructorSuiteTests and runFromJsonSuiteTests, though in some cases you
may decide to create new valid and invalid test cases to test for setValue. This helper takes in
the valid and invalid test cases, the expected value of the field for an invalid value run,
and optionally the expected text for an invalid value run if the text is expected
to be different from the value. This is the case in our boolean field and core.
Now let's talk about what's available for block test helpers. The test helpers and dev tools
provide helper functions for generating code generation and serialization tests.
Creation tests are typically straightforward so there aren't any helpers available for that.
The helper provided for running code generation tests is runCodeGenerationTestSuites.
It generates multiple mocha test suites for each code generation test suite that's defined and
passed into the function. The code generation test suite specifies which language generator to test
and a set of code generator test cases. The mocha test generated for each test case will
create a block based on the create block function which is defined on the test case and compare the
code generated from that block to the expected code and inner order defined on the test case.
Here's a code sample for run code generation test suites.
As you can see, configuration for multiple different language generators can be made and then
passed into run code generation test suites. I'd recommend defining at least a simple test case.
For an example of runCodeGenerationTestSuites I'd recommend checking out our mocha tests for
field multi-line input in Blockly core. You can check out our JSDoc for CodeGenerationTestSuite
and CodeGenerationTestCase types to learn further about how you can configure these tests.
The helper provided for running serialization tests is runSerializationTestSuites. This
helper generates a mocha test suite with the title serialization which contains two more nested test
suites for“xmlToBlock” and “xml round-tip” tests. The xml block test suite runs tests that create a
block from xml and checks that the created block has the expected structure. The xml round-trip
test suite runs tests that create a block from xml, converts it back to xml, and compares it to
the expected xml output. This helper is passed test cases of the type SerializationTestCase
which defines the xml, expected xml, and assertion functions to use for checking the block structure.
Here's a code sample for runSerializationTestSuites.
As I explained earlier, the helper function takes an array of SerializationTestCase
which define properties used in generating the tests. You can check out ourJSDoc for the
SerializationTestCase type to learn further about how the test cases can be configured.
Finally let's talk about some common test helpers. The common test helpers provided
by devtools are what's used in the block and field test helper implementations.
They are convenient functions that can also be used to run repetitive test cases or suites.
If you look at how our block or field test helpers are implemented, you can get a sense of how you
could leverage these helper functions. One of the features available on the common test helpers,
as well as in the field in block desk helpers, is that any test suite or test case can be configured
to run using the mocha keyword "only" or "skip". The "only" keyword is very useful for debugging,
and the "skip" keyword could be used to enable you to write tests that don't yet pass
due to a bug, and mark them with a skip and a to-do comment to unskip after the bug is fixed.
Thanks for watching this talk. If you have any questions you can come to our Q&A session during
our virtual summit. Or if you're watching this after our virtual summit has concluded
you can post your question on our developer forum.