Creating a DSL with your team
Using the terminology and language that everyone uses to describe your product inside the actual code that your team uses can give you a huge advantage in productivity. This is something I’ve gotten into the habit of doing with the teams that I lead and I thought it would be worth sharing.
What is a DSL anyway
DSL stands for Domain Specific Language, but in the sense that I’m using it I really use it just a way of incorporating the actual business terms that you use every day into the software that your team builds. It doesn’t actually have to be a totally separate programming language that you build. In my case I usually end up developing libraries that create the language that my teams use.
Test Engineering
The teams I lead currently are in the test engineering space, so to give you an idea I’ll use this space as a point of reference.
In our day to day we talk about lots of different products across the company. Having said that, there are a lot of terms that everyone in my space uses canonically. We talk about business priority
. We talk about versions
of the software that is under test. We talk about areas
of the product. We discuss features
. We talk about scenarios
that a user might go through in our products. These are all terms, among others, that we use in our space that everyone understands and uses every day.
What it looks like
Well, it literally looks like the language you and your team use every day. So, for example, with my current team, my leadership is making a library that has behaviors like area
, feature
, scenario
, priority
, given
, when
, then
, because these are all terms we use when we talk every day.
We take the terms we use and wrap behavior in them that helps to abstract away work from the team that they shouldn’t have to think about all the time. When they use feature
they don’t need to know that it’s creating a tag in the test that shows up in our observability platform. They just know that whenever they are creating a test script for a feature they use that to build the test.
Before
The result of going through this kind of transformation takes your teams code from looking something like this:
describe('Area: Landing Page', () => {
describe('Feature: Login', () => {
beforeEach(() => {
const span = tracer.scope().active();
if (span) {
span.setTag("priority", "critical");
span.setTag("version", productVersion);
}
});
describe('Scenario: logging in normally', () => {
describe('Given: A valid user', () => {
describe('When: they use a correct password', () => {
describe('Then: the user logs in successfully', () => {
expect(some).test.code.here;
});
});
});
});
});
});
After
to something that looks like this:
area('Landing Page', () => {
feature('Login', () => {
priority(priorities.critical);
version(productVersion);
scenario('Logging in normally', () => {
given('A valid user', () => {
when('they use a correct password', () => {
then('the user logs in successfully', () => {
expect(some).test.code.here;
});
});
});
});
});
});
This may not look like much, but when you multiply this by thousands of tests, and a plethora of conversations being had every single day, this becomes a massive productivity gain for your team.