Empowering Frontend Engineers with Microservices Contract Testing – a conversation with Markus Oberlehner

Guest: Markus Oberlehner
Expertise: Senior Frontend Full Stack Engineer & Thought Leader
Location: Austria

Podcast runtime: 36 minutes

Summary

In this episode of Specmatic’s podcast, host Hari Krishnan invites Markus Oberlehner, a senior full stack engineer known for his expertise in Vue, Nuxt, and test-driven development, to delve into the significance of API specifications and the evolving landscape of contract-driven development. Through an engaging discussion, they highlight the importance of starting with specifications, why contract testing should not be overlooked, and the challenges faced by frontend applications interfacing with microservices.

Discover how Contract-Driven Development (CDD) is reshaping the Microservices landscape! Here are 3 key points covered in this podcast with Markus Oberlehner:

1. API Specifications as Acceptance Criteria: Learn why starting with API specifications is crucial for ensuring reliability and scalability in your systems.

2. Contract Testing Simplified: Explore how tools and techniques make contract testing accessible and effective, particularly for frontend integration and microservices architecture.

3. Evolutionary Architecture: Delve into the concept of iterating on API design and the importance of maintaining executable contracts to keep everything in sync. Specmatic makes it easy for frontend engineers to adopt modern practices without getting overwhelmed.

 

Join us as we break down the complexities of testing and deployment, step by step!

Transcript

Introduction

Hari Krishnan:

Hello and welcome to this podcast from the Specmatic team. I am Hari Krishnan. I’m the co founder and CTO of Specmatic. I will be your host today. I’m thrilled to introduce our featured guest, Markus Oberlehner. Markus is an industry thought leader and senior full stack engineer with expertise in Vue Nuxt and a passion for test driven development. He’s a seasoned practitioner of react, Next JS and Remix, as well as an avid Node JS enthusiast, Markus also is exploring and learning machine learning right now and he considers himself a true ML Badhavan.

Navigating Modern Challenges in Application Development

Hari Krishnan:

So Markus, why don’t we start off with your general experience in terms of the current state of affairs and building applications. I know you come with a lot of expertise with single page applications and server side rendering, so I’d love to hear your thoughts in the current state of the industry and difficulties that teams are facing and your general ideas around that.

Markus Oberlehner:

Yeah, so I think, of course, one big thing that’s currently in the room is how AI will affect development in the future. And this is also something I think a lot about. But what was mostly in my mind in the recent months was how can companies who just start out with going into the direction of more microservices based architectures or even going into the direction of migrating to the cloud, how can they solve the problems they face when doing so? Because I think what we currently still struggle is that there are no really not a lot of best practices that are broadly communicated. And I think that’s an important topic we currently still need to tackle. And of course, there is also the topic of AI, and that is something that’s also very on the top of my mind.

Microservices and Frontend Development Challenges

Hari Krishnan:

That’s great. Thanks for bringing those two topics up. Those are close to my heart as well, especially with microservices. The promise was that we’d all have the next best thing since sliced bread and we could all ship services independently and make progress. But that’s hardly the case. And especially with frontend teams that I work with, they’re often complaining that I cannot start building independently, I cannot deploy independently. That’s a very often cited issue. What is your experience in terms of that?

Markus Oberlehner:

Yes, I think one big problem that hides behind all this is that many of us coming from a world where we have batteries included frameworks, like when you come from a Rails world, for example, with Ruby on Rails, you have a framework where you basically are on rails. So you can not really deviate. But that’s also a good thing because with a framework like this, you know exactly how to solve certain kinds of problems because the framework is telling you how to do it. But what we are now facing in the frontend world, and also in the frontend world in combination with the microservices back end world, is that there is more flexibility. But the flexibility also comes with the cost that we need to figure out a lot of this stuff ourselves. And one big problem I see there is that there is this problem of not knowing what you don’t know. So a lot of teams get started with building microservices and get started with using react to build the frontend application because that’s the way you do it nowadays. But because there’s so much flexibility, first of all, you have a hard time choosing the right tools that fit your needs.

And also you don’t know, maybe you don’t know that you need something like that. You need a different technique for testing, for example. You don’t know that because you only know what the frameworks provided you. And now with more custom architecture like it is mostly with microservices, you need to figure out a lot of this stuff yourself. And if you don’t even know that you have a problem that you need to solve, it’s obviously hard to solve the problem. And even if you know that you, for example, that you need to find a way how you can test your application in the context of this microservices architecture, then there are not really derails laid out for you as it is with those more batteries included frameworks that rely on a traditional monolithic architecture. So I think this is something where we have a lot of work to do, and I’m not quite sure what’s the best way to tackle this, because in the case of frameworks, there is the framework as an authority which can state, yeah, if you need to test your application, you can use those tools and you can use those techniques, and there is this one single information source where you can get and where you can learn how to apply best practices. But with microservices architectures and maybe even with micro frontends, there is no single authority which can say, yeah, you need to have tests in place and you need to have a CI pipeline that solves those and those this and that problem.

And that means you have to figure out all of this yourself. And this in turn means that you need to have a very high level of expertise and a very high level of maturity in your teams and yeah, as I said, not quite sure how the best way is to solve this. I try to educate people more, like with talks and articles and stuff like that. But yeah, it’s definitely a harder problem to solve for companies and teams when they go around where they don’t rely on a monolithic architecture.

Hari Krishnan:

But microservices, I can completely relate to that. All of the snowballing into integration help when all the microservices and frontends come to that last point and then figure out their issues. And what has been your experience with this that we work? Usually that happens with integration. Is that something that also has been an issue with the teams that you’ve been working with?

Markus Oberlehner:

Yeah, what I noticed is that it’s very easy to fall back into old habits. And if you are coming from a monolithic application and now you say you want to grow microservices, it’s very easy to build a distributed monolith instead truly microservice oriented architecture. And this is something I think we struggled in the past with that. Although we wanted to build truly independent microservices which are decoupled from each other and can deploy it independently, we didn’t solve all of those problems that microservices are supposed to solve. So maybe we had the independent deployability in theory because it was a standalone pipeline for each microservice. But in practice, if you can’t know that your microservice you are just deploying works with all the other services, then is it really independently deployable? Not really, I think, and this is something we struggled with.

 

Contract Testing and Implementing Best Practices

Hari Krishnan:

I’m curious to know. My first introduction to you, Markus, was through your brilliantly written a article about contract testing and reviews on it and how it helps in this particular area. It would be great if you could share your experience as to how you discovered contract testing itself and how your personal thoughts have evolved around that area over time.

Markus Oberlehner:

Yeah, so I think typically when you think about contract testing, it’s all about testing that services work together so that the contracts between services are in check. But I’m coming more from the frontend world and thinking more about frontend applications and how they integrate in the microservices architecture. So probably my point of view isn’t the most obvious one when we talk about contract testing. But still, it helped me a lot to, to see the value in it because the problem I faced was, okay, so now we had this microservices based architecture and we had a couple of frontend applications as consumers and we wanted to test our frontend applications in isolation. And different teams solved this or tried to solve this problem in different ways. And this is exactly what I said previously about there are no agreed upon best practices because there was one team that had mostly real end to end tests which didn’t test their frontend application in isolation, but together with all the microservices, which meant that the tests were slow, that they were flaky, and also that they couldn’t test everything they needed to test because they don’t have control over the microservices during the test run or very limited control. They can’t say yeah, for this test I need this data set, for example, it’s not really possible, at least it wasn’t really possible with our setup. And then there were other teams that used mocking, so they mocked all the requests to the microservices.

And although this is a way to go, it only really worked for our single page application. So for our purely client side rendered applications with mocking we could solve this problem. But then we also had applications that were not purely single page applications, but we were going more and more in the direction of having client side applications that have a BFF or client set, applications that frontend applications that have traditional server side rendering. And when this is the case, then all the requests that your frontend application makes to the microservices are now going through the backend layer so you can’t really mock your requests anymore. And this is where I was thinking hard, how can we solve it? And then I already knew there’s contract testing, but mostly thought about it in terms of testing the contracts between microservices and not so much about how we can use it for frontends. But when I had this click moment in my head when I realized oh yeah, especially the way how Specmatic is doing it, by relying on OpenAPI specifications for for the contract. Then I realized that we can use those open API specifications that we want to write anyway because we want to go in API first route, we can use those to run stub servers and now the stub servers, we have control over them so we can tell the stub server hey, when this test runs we need those data and when the other test runs maybe need an error response because we want to make sure that error handling works correctly. And now this was possible again.

And this was really a revelation for me to finally find a solution how we can test this frontend applications that now have a server side layer again and don’t need to mock requests made from the client side part of our frontend application to the server side part can test the whole application and only stop the requests made to the microservices. I think this is the way to go and this is one of those best practices that I think are not really common knowledge yet. So a lot of teams have either no solution or not really good solutions. A lot of teams I see are having real intent tests, for example with the problems I described earlier or but don’t test things that are hard to test and stuff like that. And I think we need to get better at this and I think this is at least for now, the best way I see to achieve this.

Hari Krishnan:

That’s great. And in fact, what I can relate to is the point you were mentioning, the hard to test aspects of a frontend application, like what if the backend is slower to respond? Or what if there is an error in the backend? Simulating that is hard even in a higher environment. But if you are mocking it with specmatic, you could potentially do fault injection there and then test how frontend itself in isolation behaves. And yeah, that testing applications, be it microservices or UI frontends in isolation is really critical because that’s when we get quick feedback. Completely agree with you on that and you’re in the future. Like you said, this is an area which is not common knowledge yet. I think people are still warming up to the idea.

Unlocking the Benefits: AI and Machine Learning in Testing

Hari Krishnan:

So what would you think this idea should evolve in the future into? And especially given your leanings on ML and AI and how testing is evolving with that? And if you put that context in mind, how do you suppose contract testing and API contracts will evolve in the future? How would that be a way for teams to work in a more productive manner? Any thoughts on that?

Markus Oberlehner:

I think the teams that already are using good best practices, teams that already are practicing API first approaches for example, and teams that already rely on test stream development will have an even bigger advantage in the future. I think already without AI, it makes a lot of sense to work API first, to work in a test driven manual, and to have contract testing and stuff in place. But it will give those teams that already practice those things a head start. I think when they switch to tools that generate code for them using AI technologies. Because when we look at current LLM technology, most of us know already at least the basics of how it works. It can only be as good in predicting the next thing as the input makes it possible to predict a good or to make a good prediction. And the more context you give it, the better the prediction will be. And what I mean by that is that if you tell your AI programmer to please program this or that feature for me without any further context, it will most certainly not be a code that you can use in production in your application.

As it is, if you write the feature for an existing application, at least you need provide it with the code of your existing application and will already be better if you do that. But if you give it more context, like you do, when you work in a way where you have specifications first, where you have API first, and where you have your tests already in place, and where your tests clearly state the outcomes you want to achieve, the better the result or the better the predicted perfect result from the AI will be. So if you apply current best practices, I think it will help you very much in building applications with the AI systems in the future. So currently, if you think about best practices for product teams, building digital products is you start that out with user research. So you ask your users, or you try to find out what your users really need, what outcomes they want to achieve with your application. Because otherwise you’re just building features and you are building a feature factory. And maybe your features work good or not, but if they don’t do what your customers need and they are worthless regardless of how well you program them. You start out with user research and then you have user stories based on this user research.

This is your first bit of context, of very valuable context, not only for the AI system, but also for human developers. So that’s the nice thing about working about already using best practices. That now that will help you in the future is that they already work now and many are already doing them, but a lot of people are not doing them. So from this you can have certain acceptance criteria. For example, if you are working in the healthcare industry, your acceptance criteria can be that it’s very reliable. Or if you have, if you are in maybe an acceptance criteria, is that you survived a Black Friday request search and stuff like that. And again, you have more context. Now you have the user story and you have acceptance criteria.

And from that you can write your automated tests which make sure that you fulfill the acceptance criteria and that you fulfill the outcome that is specified in your user story. And again, you have more context. And with all this context now, it’s very likely that the EI system will generate a better outcome than it would if you just simply say, hey, build that feature, because now it knows the intent and now it knows exactly what are the criteria the code needs to fulfill that, that the test passed and stuff like that, and you will reach a better outcome doing it that way. But you also have the tools you need to deal with certain shortcomings of AI systems. So the AI’s, as most of us already experienced, are prone to hallucinations, for example. So they make up stuff that looks plausible or sounds plausible, but it doesn’t really work. And if you don’t have automated tests in place, and if you don’t ensure, maybe even if you let AI write those tests, but if you don’t ensure they are correct, then you have no way of knowing if what the AI produces for you is correct. And so those are all important pieces, I think, even now, even without AI.

But they will become essential when we have AI systems, especially automated tests, in some way. So in some way checking if the changes the system makes are valid and do what we expect it to do. I think it will be a mission, critically, to have really solid automated tests in place in the future, even more so than now.

Hari Krishnan:

I think that’s a very nuanced view, and I’m glad you went into such detail. It’s not just about magic. AI is not magic. There is hard science and engineering, and like you said, there has to be that checks and balance. Even if you are generating both the source code and the test, they both have to have some sort of a guardrail. And that’s exactly the kind of thought process. Also, we are aligned on by means of making specmatic, you know, taking openap specs and making them executable contracts gives free tests. But then that’s acting only as a guidance for the rest of the pieces.

API specifications are indeed acceptance criteria for the API, one sort of an acceptance criteria. And also like, it’s a good point which you brought up, which is how we slice our, you know, the stories and the acceptance criteria, like we call it the “ilities” slicing, which is the reliability, scalability, all the “ilities”. So all of those good practices definitely add up. And it’s not just about like, suddenly I’m in the AI age, I don’t need to worry about any of the good stuff that we’ve learned. The fundamentals still matter, and that’s what will actually amplify with AI.

Advice for Beginners in Contract Testing

Hari Krishnan:

So, and what would be your advice for someone who’s embarking on a journey of like say, adopting contract testing or new to it? And what would be your general suggestion as to where they start and what they focus on? Because I see a lot of confusion. When they take it on, it looks like a very daunting topic, and then people shy away from it or actually have bad experiences and like, you know, they leave out such a beautiful technique. I’d love to hear from someone who’s been a practitioner and a thought leader in this area to talk about.

Markus Oberlehner:

So if you are not familiar with something like testing, then it seems like, like such a big thing. It’s, it’s like this, this confusing big topic, and you, you don’t want to have do anything with it. So. And I experienced this with a couple of things. So when I was new to testing, testing was, for me, this must be complicated. So in my head, testing is this complicated thing, and it must be above my pay grade, basically. And then you get into it, hopefully because you are motivated because of some reason, and then you notice that, no, it actually isn’t that complicated. This would be my first advice is don’t assume that something you want to learn or you need to learn is too complicated for you.

I had recently, I was learning a little bit about machine learning, and I was completely new to the topic and I was completely new to even Python. So before, I never wrote a single line of python. And so this was, machine learning must be very complicated because there is a lot of maths involved, and then there is this programming language I don’t know. So it’s this huge, really this huge barrier to entry, I thought. And then I had some idea, and this idea what I want to solve with machine learning. And this idea sparked a lot of motivation. And then I realized that if you go step by step, actually, it’s not that hard. Things are not that hard, especially things that are already established in the community, like with machine learning.

Of course, the science behind it is hard, but if you are a regular machine learning engineer, you don’t have to fully grasp the science behind it, at least not at the beginning. And so this is a recommendation if you want to learn anything. But for the matter of this podcast, if you want to learn more about contract testing or testing in general, don’t assume that it’s this big complicated thing, but assume it’s easy, at least it’s learnable. And there are people who already thought hard about it and made tools that make it easier. It’s actually, it is that way. So with testing frontend applications, you have tools like Playwright, which make it really easy to write tests for your frontend application. And with Specmatic and certainly other tools in this area, you have tools that make it easy to even write contract tests. So don’t assume it’s so hard and it’s above you.

So this is, I think in general for learning anything, it’s the mindset that matters. And more specifically about contract testing, I think testing in general and writing large system in general is get more into a specification first mindset. So there are some that argue that testing is even the wrong word for it, because testing somehow feels like something you only do after you are finished with something and then you test it and make sure that it works correctly. But I think that’s the wrong way of looking at it. I think if you want to get into testing, if you want to apply best practices on how to build or more complex systems like microservices architectures, is get into this specification first mindset, think in terms of API first. So instead of going right into the code and write some code, and then you have to later change the code again and always do manual testing to make sure if the code that you just wrote and the code that you changed again does what it should do, turn it around and start with the specifications. Start with thinking about I need the following API, and this API needs to solve the following use cases for certain types of consumers. And how can we ensure that everybody is happy and sit together with the teams that will consume your API and think about what are the needs that you need to solve for them, and then come up with the specification.

And then from the specification you can go to the code and coding will be a lot easier that way and the outcome will be a lot better for everybody. That I think is my recommendation for people who first of all go the route of building more complex systems, more distributed systems, and especially for people who want to start with complex testing, think about the contract as a specification, as it says, as a contract that must be specified before you really start the hard work. And one important point, do not get confused, but is this does not mean that this contract is set in stone. So you can always change contracts, but everybody has to agree to the changes. This is the important part.

Hari Krishnan:

That is excellent, I think. I’m so happy you brought up two important points. API design first is like, I’ll go with reverse order. API design first does not mean it’s waterfallish, right? It’s evolutionary architecture. You can iterate on the API design does not mean you have to set in stone on day one. I think that’s a misconception that does exist. So thanks for clarifying that. And like you said, the word testing sometimes can have, like other connotations you know, even with test driven development.

As a fan of Kent Beck myself, I always thought of it as test driven design. It’s both the design of your code and your system, rather than just writing a unit test and having the contract in place first pushes us to think about the systems we are designing. That design is more important and actually the code that comes in place. So it’s brilliant. I think that’s great advice. I’m sure this will be very useful to our audience.

 

Recommendations for Specmatic and Improvements

Hari Krishnan:

I would also love to know, as someone who’s been using Specmatic in anger for some time now, what is your feedback for our team? Anything that we could improve on? We’d love to incorporate your thoughts into our roadmap and we’d love to hear in general about what you think about the tool.

Markus Oberlehner:

I’m really a big fan of Specmatic and how you tackle it because other tools I know for contract testing mostly have their own custom specification format and I’m a big fan of using the default or the standard openapi specification. So I think the overall feedback, it’s an awesome tool and everybody who nothing using it nowadays should use it. I think for complex testing and for things that could be improved, I think there could be more showcases, for example, how to use it with a tool, because I’m coming from the frontend world, how we can use it for testing our frontend applications with playwrights, for example, and have more opinion, at least recommendations for how to do it and stuff like that. I think this would be really valuable for teams to have something that they can look at and just implement it that way, and that they don’t need to think about this too much themselves. So nowadays it’s a very flexible tool you can use in a lot of ways and this is awesome. It’s really great and I think that’s also a design consolidation of yours, I guess. But it helps a lot of teams who are less mature and who don’t know or are new to the topic and who don’t have the resources to figure out so much stuff. For those people, it probably would be very helpful to have like to have like a default way of doing things with certain tools and certain frameworks and stuff like that.

Hari Krishnan:

Absolutely. That’s point well taken. Again, thanks for the kind words of feedback. And I know it is quite lacking in the frontend area because again, coming from where we are like Specmatic was, predominantly on the back end. And then we’ve constantly been reminded of the fact from experts like yourself that it has so much value for the frontend engineers. They’ve always been on the camp of supporting the cost. So certainly we need to put our efforts in there. And like, your idea is correct to have that some examples which can be directly followed, or an opinionated framework aspect which can be incorporated.

Hari Krishnan:

So that’s certainly something we’ll look into.

Markus Oberlehner:

I think that’s the beauty of Specmatic, is that although you probably didn’t intend it to be used also very much by frontend engineers, it’s built in a way that it’s very easy for frontend engineers to use it for their use cases as well. So it’s really a beautiful thing, actually.

Hari Krishnan:

I’d be happy to hear, if there is anything else that you would leave our audiences with, any other pieces of wisdom that you would like to share with our audience. Happy to hear that.

 

Final Thoughts and Encouragement to Learn New Technologies

Markus Oberlehner:

Oh, I think I want to reiterate two points. First of all, because I recently, as I said, I had the experience myself, if you first of all, learn new things and go ahead and learn new things, and don’t be intimidated by things that look complicated or have complicated names, like recently, machine learning. Also, testing is something I know that a lot of people think it’s so complicated and it’s above my head how to do it. Don’t think that way. Adopt the mindset of everything is easy if you take it step by step. So I think this is one thing I want to mention here.

And I also want to reiterate; think more in terms of specification first. Especially for the more complex systems you work on, the more important it is to turn it on its head and think about the specification first before going too deep into implementation. And as you already pointed out, don’t think that this means, in turn, that you have to know everything perfectly before you get started. That’s not the point here. The point is that you have a solid base where to start, and that you have to actually, it’s quite the opposite. With contracts in place, with specifications in place, you have one source of truth where you can make changes and actually propagate those easily to the rest of the system. So actually working specification first makes it easier for you to make changes in the future. So adopt this mindset. The more complex your systems get, the more important is it to think about specifications.

Hari Krishnan:

Thanks again for your time, Markus. And I’m sure our audience will benefit greatly from this conversation of ours. And, yeah, and we’d like to thank you on behalf of the team and for our audience do like and subscribe to our channel so we could have more such distinguished guests as Markus in the future. So thank you.

Markus Oberlehner:

Thank you for having me.

More to explore