2 Weeks in the Life of a Shortcut Engineer
Hi, I’m Evan. I’m a software engineer at Shortcut. As part of the engineering team, we try to make Shortcut better and better all the time so it’s something that you (and we) love to use much more than Jira.
From an engineering perspective, I thought it would be fun to share what I’ve been up to here at Shortcut. So this is a brief overview of two weeks in the life of an engineer (that’s me), - and why, sometimes, Stories take longer to complete than you initially think they will.
For context: I'm currently working on an Epic to build a bare-bones CSV import experience internally via the Admin UI. After digging around a bit, I figured out what part of the import needed to change to show a name for the import for users in the app. Building that functionality takes about 5 lines of code changes; easy peasy, I thought, let's bang out the tests and move onto the next thing!
Except, to do that, I have to mimic a file upload in our testing code, and I have to do so for the Admin UI, which is slightly different from our app. So I went to see if there were any helpers built for this already. Here we go.
Step One: Any existing functions that already do what I need?
First up, I go looking for how to send a test request to a test instance (local to my machine) of the Admin UI. I find a function, “make-admin-request”, in our local test-request helper namespace in our repo. It's doing a lot, but does it do what I need? Specifically, can it make a multipart file upload request for me?
To answer that, I have to go look at the code for how the Admin UI parses multipart requests. This leads me over to the webserver definition in our repo, and a whole bunch of digging around to figure out how multipart requests are parsed. I read through three functions in that file, about 20-30 more functions in that file or in other files, and eventually into the source code for a library we're using, and then into a library our library is using. Finally, I discover that the way the existing function sets up multipart file uploads will not be picked up by the Admin UI, which means I've got to make a decision.
Step Two: Fork in the road
While the function I found is promising, insofar as it's being used in other tests to make test requests to the Admin UI, there is a lot going on with it. It’s not clear what I'd need to change, or how I would need to change it to avoid breaking other tests.
I ask the other engineers if anyone has experience with doing file upload tests with the Admin UI, but no one does.
Luckily, we've also got a function called “execute”, which is used to make test API Server calls, and it has less code while still seeming to support file upload tests for the API server.
Given this, I decide that the best option is to figure out how to support Admin UI requests with the “execute” function.
Step Three: Montage
Okay, please envision a really sick montage while you read this section!
There are about two weeks worth of work in this montage.
To make this work, I had to solve the following problems:
How does our test code figure out which function to send the request to?
This involved digging deep into our testing code, as well as Peridot, which is a supporting library we use (and then, in turn, libraries it uses).
How do I handle CSRF tokens in test requests?
This is normally handled for you via your browser, but we don't have a browser here, so we can't use that…
Wait, has anyone built a test function to handle authentication for the Admin UI? It's different from the API server...
I lucked out with this one, because someone had sorted that out. Hurray!
How do I turn our Admin UI app into something that can take the kind of request that Peridot will hand it?
This involved reviewing a lot of prior art, and digging into Peridot, again, to figure out how it chooses the function to use, and what kind of thing the Request it sends is.
Okay, I did that, why doesn't the request get parsed properly?
This one was the hardest. By this point, I'd pulled out every tool from my tool bag to debug what was going on, then invented another tool, and went and found a couple new tools to boot.
All told, I had to trace the test execution across its whole lifetime in the system, following it through just about every function, narrowing down the plausible causes until, eureka! I discovered that one of the libraries we use feels a very particular way about how HTTP Headers (metadata for your requests, essentially) should be cased.
That is, if I send it a header like “content-type: multipart” -- which will tell it that I'm sending a multipart request, and it should handle it appropriately -- it will pretend it never saw it. Why? Because it'll only respect headers Cased-Like-This.
Step Four: Success! And Learnings
And with that, the tests were written, and the work could move on to the next phase.
So, what did I learn? Put docstrings on everything. Spend extra time when writing your code to document the whys and the implicit hows. While one of the pieces of information I needed was available in the Peridot Readme, most of the info I needed - both in our code, and in the libraries we use - wasn't available anywhere except in the code itself, often several levels deep.
Hopefully all this gives a sense of why estimates are hard, and why some things take longer than we'd like. But in the end - success!
Use Shortcut
Shortcut is project management without all the management. It’s built by our software team for your software team. It’s designed to help bring product and engineering teams together, and help everyone succeed. Try it for free.