I spent a lot of years consulting at a lot of companies. My specialty was codebase assessment, often for the purposes of legacy rescue and remediation. To be less fancy about it, I helped companies with code quality problems.
Perhaps not surprisingly, unit tests (or lack thereof) featured prominently in many of these engagements. Teams with robust, well-maintained unit test suites tend not to need help getting back on the rails. So part of the write-up would kind of write itself. Rework your code toward modularity and testability and get it under test.
When explaining this to teams and leadership, I would always hear a curious variant of the same mantra.
Oh, well, unit testing is a unique challenge here because we’re different in the following way: ___________.
To understand what I mean, here is a list of things that I’ve actually heard.
- Unit testing is impractical here because we have a hardware component to our product.
- We can’t unit test here because we’re an app dev consulting shop and our clients wouldn’t want to pay for it.
- Unit testing wouldn’t work here because we’re mostly just a web service.
You get the idea.
Today I’d like to dive a little deeper into this theme by picking a vertical. Specifically, let’s talk about banking.
I’ve consulted at a number of banks. Some of them had unit tests, some of them really didn’t, and some were working their way to testing joy. But tests or not, they cited a lot of common challenges in trying to get the code under test.
So let’s take a look at some of the common unit testing challenges in the banking industry.
1. Dealing With Old Technologies in General
We might as well get this out of the way early. Many banks tend to have and depend on a lot of old technology.
Unlike, say SaaS companies, most banks have been around for quite a long time. Long enough, in fact, to have navigated from paper files to mainframes to more modern concerns. But they don’t necessarily shed all of that baggage, even as they modernize entire segments of their business.
So go into most established banks’ headquarters and significant offices, and you’ll find mainframes, really old applications, and programming languages long since sunset.
On its face, this makes unit testing difficult. The practice didn’t really become mainstream the way we know it today until the early 2000s. So if you want to setup unit testing around these techs you often have to retrofit it creatively. Naturally, this doesn’t happen frequently. This means that changes to these systems usually happen without any kind of safety net in the form of unit tests.
2. Friction Associated With Regulatory and Other Compliance
The presence of a lot of old and legacy systems isn’t the only source of friction and inertia related to unit testing within banks. Just as large a culprit tends to be the bank’s risk footprint.
You might have noticed at some point in your life that banks tend to handle lots of money. And when companies handle lots of money, they find themselves subject to a dizzying array of compliance standards and regulations. It’s hard to complain about this as a consumer since it means that you can count on the bank having your money when you show up to withdraw it.
But all of this regulation means all areas of the bank spend a lot of time vetting and re-vetting everything they do and use, including their technology. So if you want to adopt something like, say, a unit test framework, or a mocking library, you have a lot more work to do than you would at a Silicon Valley startup.
In a bank, you’re going to have to get legal approval to use the library, for starters. The security group, the architectural standard group, the purchasing department, and various other entities may also come a-callin’ if you want to use that test framework.
Of course, this applies across the board to everything you’re trying to use, and not just test frameworks. But when it comes to testing “we couldn’t get this mocking tool or that framework” approved is a common hurdle to clear.
3. Old School Leadership Views
Switching gears a little, let’s talk leadership. If you go into the world of location independent startups or Silicon Valley, you’ll find people at the bleeding edge of technology. But you’ll also find people at the bleeding edge of management philosophy as well. That’s where you’ll find concepts like The Lean Startup, Holocracy, and whatever else the cool kids are doing these days.
But head to the enterprise and, more specifically, the banking/manufacturing/retail world, and you’ll typically find more traditional approaches. This is true across the board and, by deduction, in the software group besides.
The consequence? You’ll find a lot of leadership with more traditional views on IT and software, viewing it as a cost center, and viewing source code as a material asset in the same way as inventory. With this worldview, unit tests are actually illogical.
It’s extra code, which takes extra time to write, and “testing” is supposed to be QA’s job anyway. So, to this line of thinking, it’s waste three times over. It takes up space, wastes developers’ time, and forces half of your people to do the job of the other half.
Sure, there are agile transformations in place and consultants working overtime to try to counteract these notions. But they’re not quick to die.
4. Mainframes and Other Test Resistant Dependencies
Recall that I’ve already mentioned mainframes and other legacy techs as a source of unit testing difficulty. But in the first section, I meant that it was hard to test these things, themselves.
And, that’s true. It is. But it’s also hard to test the code that uses them, even if that code is modern and even if you’ve sold management on testing and gotten sign-off from all required departments. Why is that? Well, think of the style of code that folks tend to write in banks.
Often, it’s glue code. They’ll have some COTS solution or old mainframe at the heart of their operations. And then they’ll write services that pop data out of some ETL feed and stick it into some other system. This style of programming is a lot more common in the banking industry, outside of the high frequency trading algorithms, than building large, stand-alone greenfield stuff.
And this glue style of code can be some of the hardest there is to test. Most of it makes calls to databases, web services, mainframes, etc. This means that it requires heavy mocking and isolation to test it. And those are advanced techniques in unit testing, which can discourage adoption.
So the old stuff at banks can make it hard to test even the new stuff.
5. Superficial Unit Testing Approaches
And, finally, team members in banks face challenges even once they’ve bought into unit testing, gotten everything approved, and started in earnest. I’m talking now about shoddy adoptions and metrics that miss the point, and this is a good note to close on because it’s a little more philosophical.
One of the most common unit test adoption anti-patterns I see at all sorts of organizations is this. Management perceives a quality problem and, finally shakes off old thinking. “The consultants say we need unit testing, so we’re going to roll out unit testing. We can measure our unit testing maturity with metrics like code coverage and number of teams in compliance with coverage minimums.”
Superficially, this sounds promising. But it tends to lead to counterproductive approaches and genuine waste in the form of useless unit tests.
Good Unit Testing is a Long Game
If you give a team a metric to hit, they will hit that metric, even if they have to burn the company to the ground to do it. So if you demand unit test coverage to help you improve code quality, you will get… unit test coverage. And that’s it. Trust me—it’s really easy to write “unit tests” that generate a ton of code coverage and literally test nothing.
And your teams will do this. Not to be duplicitous or malicious, but because they need to ship software in a hurry and the build fails unless they hit 50% coverage. So they write the useless test, promising themselves that they’ll totally come back in later and spend time writing actual, good tests. They never will.
So in closing, note that there are a lot of barriers to unit test adoption in the banking world and in general. But there’s no barrier bigger than thinking you can get there with shortcuts and superficial approaches. It’s a long game.
This post was written by Erik Dietrich. Erik is a veteran of the software world and has occupied just about every position in it: developer, architect, manager, CIO, and, eventually, independent management and strategy consultant. This breadth of experience has allowed him to speak to all industry personas and to write several books and countless blog posts on dozens of sites.