Recently I’ve been working on the EveSDEImporter project. I’ve got enough logic written to start writing unit and integration tests. Once I’d figured out how to get the first minimal unit test running with Catch2 I began to write actual tests and was quickly reminded of a major benefit of unit testing: It will show whether or not you understand what your code is supposed to do, what it is doing, and the frameworks you’re using.
For me this came in the shape of not understanding YAML or the way that RapidYaml represents it in code. In this post I am using the following:
- Test Data – agtAgentTypes.yaml from the Eve Static Data Export
- Note that I grabbed the first couple lines from this and hard coded it in the test to have a small set of data to reason about in the test.
- Test Code – parser_tests.cpp
What Were My Incorrect Assumptions?
The data and setup that I used in the test looks like this:
std::string str = "- agentType: NonAgent\n agentTypeID: 1\n- agentType: BasicAgent\n agentTypeID: 2";
std::vector<char> data(str.begin(), str.end());
SDEParser parser(data);
ryml::Tree parsedData = parser.getParsedData();
In this test I am simply trying to make sure that the RapidYAML parser is ingesting YAML in the way that I expect it to. While writing the assertions to test my expectations I found that I had two things I thought I knew that were wrong:
- RapidYAML makes the size of the resulting tree the number of sequences in the data.
- The root of the tree that is returned is a sequence given that the YAML is a sequence of mappings
These are fairly simple assumptions that turned out to be wrong. The first assumption was wrong because RapidYAML returns the total number of items in the tree (this is reasonable). The second assumption was wrong because RapidYAML doesn’t intend for you to ask whether a tree is a sequence (because it, as a whole, isn’t). It intends for you to ask such questions about nodes within the tree. If you would like more details about why these assumptions were wrong, read on! If you’re here simply for the TL;DR – don’t hold your assumptions with a tight grip because your unit tests are likely to prove them wrong.
How Is The YAML In Question Organized?
The YAML in the example above is organized into a sequence of mappings. Maps should be familiar to many developers. They are, in general, structures containing key / value pairs. Sequences, on the other hand, have a more specific meaning to YAML in this case: they are a group of objects (mappings in this case) one following another.
In this test case the YAML contains:
- Sequence #1
- Mapping – agentType : NonAgent
- Mapping – agentTypeID : 1
- Sequence #2
- Mapping – agentType : BasicAgent
- Mapping – agentTypeID : 2
As you can see here, these sequences easily represent database records. The keys of each mapping in a sequence represent the schema and repeat across sequence, the values are the database values, and each sequence is a record.
How RapidYAML Presents The YAML
RapidYAML has several types that are involved in parsing YAML:
- Tree
- NodeRef
- The notes for this happen to be under the description of the tree.
When parsing a document RapidYAML will return a Tree structure as seen in the code sample above. Thee responsibility of the tree is to provide information about the parsed document and the ability to iterate through the nodes in the tree. While the tree object can technically be considered as pointing to the first item in the tree / the root of the tree the tree itself is not what the API that RapidYAML presents expects you to use for interacting with a particular item in the tree. That honor is reserved for the NodeRef object.
Set Your Expectations But Hold Them Loosely
Having received failures for the expectations I set in the test, read up on why they were failing, and correcting my expectations I’ve come out of this situation with a lot more knowledge that will allow me to continue with this project. As a developer I have to write my code with my current level of understanding but have to remind myself every day that, if I find that I have an incorrect understanding, I have a situation where I can learn. It is not a situation where I am a failure but one where I’m growing into a better developer. Unit testing is one of the many tools that I can use to grow myself into a better developer.
If you’ve made it this far in this article, thank you! Please check out another of my posts on unit testing: How Do I Start Writing Unit Tests For An Existing Code Base?