Out of the questions that customers ask about TestLess, the one that crops out the most is: how can I create my own TestDetector for my language and/or test-style of choice?
In other words: how do TestDetectors work?
I’ll clarify and answer those two questions in this post.
TestLess comes equipped with several TestDetectors out of the box. For example, there’s a TestDetector for Ruby’s test::unit, there’s another for Ruby’s Rspec, another for Python’s PyUnit, et cetera.
Since each language naturally has its own characteristics (such as syntax and grammar), and each test-style is also different, TestLess needs a way to know how to handle such differences in an efficient way. That’s where TestDetectors come in.
TestDetectors specialize in handling different languages and test-styles so that the Ortask Comparison Engine (the technology powering TestLess) can handle as many possible languages and test-styles.
But how do they work?
Below is a sequence diagram that shows exactly how TestDetectors work.
TestDetectors are fundamentally very simple state machines, each handling their own language and/or test-style.
There is a “master” (or parent) TestDetector containing most of the logic for the state machine. Then, each specific language or test-style trait — such as syntax, whitespace, et cetera — is handled by a specific TestDetector_X that extends the parent.
The parent TestDetector includes both behavior and data to handle most of the general logic, including:
- Detecting the beginning of a test
- Saving the contents of a test
- Detecting nested contexts (such as with BDD-style tests)
- Detecting the end of a nested context
- Detecting the end of a test
Along with all these “happy path” secnarios, the parent TestDetector also strives to handle invalid or malformed tests by stopping the processing as soon as something wrong is detected, and issuing an alert to the user.
Generally, you do not have to modify the parent TestDetector. However, if the current parent TestDetector does not fit your needs, then the sequence diagram above will make it super easy for you to know what and where to apply changes.
Now, the specific test detectors, or TestDetector_X, contain mostly data and some behavior (the parent TestDetector handles most of the behavior and logic already, as stated above). In other words, a specific TestDetector_X contains the data necessary so that the parent TestDetector can properly identify tests, such as:
- the pattern to look for that indicates when a nested context starts
- the pattern to look for that indicates when a nested context ends
- the pattern to look for that indicates when a test starts
- the pattern to look for that indicates when a test ends
As you can see by the sequence diagram above, the parent TestDetector accesses these patterns from the specialized TestDetector_X at certain times and uses them to determine when a test starts, ends, and when contexts start and end.
I hope this explanation has proved useful and has answered your questions about how TestDetectors work.