Luca Piccinelli

Fast Prototyping With Azure Functions and TDD

I Had an Idea

There is a colleague of mine, Dario, who gives great happy birthday greetings.
Everyone in the office is happy to receive an audio greeting from Dario. They say, “it is not a birthday until Dario sends you the greeting.
So why not let everyone in the world be greeted by Dario on their birthday Do you want to try it out?
https://telegram.me/HappyDarioBot

At the moment it is only in Italian (sorry).
Github repository here:

Ok. How?

I need an easy way for people to ask for greetings. Website? Who still uses a website in the platform era? Platform then. Which one? Facebook? Twitter? Or maybe Telegram? Usually, Dario distributes his audio notes using WhatsApp. I want to let him stay in his comfort zone, but you probably know that WhatsApp puts many limitations on bot developing. So, Telegram is the choice!

Ok. Where?

Where to host the bot? The answer depends on the business needs and the technology choices. In this phase of the project, I need to be fast! I don’t want to spend time on something that maybe no one is going to use. I need to know if someone is going to use it as soon as possible. Hence, fast is the priority. Currently, I’m developing with Kotlin, but as I developed with C# for many years, it’s still the language that I’m most effective with.
I need also to store audio files and some simple unstructured information.
What’s the faster way to host something written in C# with access to simple storage? The answer is a serverless hosting. For C#, Azure functions.

Quality

I said fast, that doesn’t mean I accept low-quality code. In the lucky scenario that someone is going to use this, I want to let it grow without rewriting everything.
How to be fast and maintain an acceptable level of code quality? Test-driven development is the answer. I went deep about my experience with it here. To summarize, it takes some time and practice to get used to it, but once you are into it, it’s the fastest way to develop and ship something in the real world.
Actually, enhancing speed is not only about TDD. It is a golden triad of techniques:
  1. TDD → put in safe your business value
  2. Incremental approach → do nothing more than what you already know that is valuable
  3. Simple design → keep it simple and modular
Those are related. TDD enables incremental approach. Incremental approach improves simple design.

How to Do TDD With an Azure Function

TDD is not trivial at all. One of the most difficult questions to answer is “what to test?”
The HappyDarioBot Azure function is receiving a Telegram update via Telegram webhook. Then it processes the update and sends back a Telegram message. This answer message depends on some business logic.
Seems like I don’t own neither the input nor the output.
What to test then? Should I post a request to the bot over HTTP and then use some Telegram API to make sure that the message has been actually received? How long is it going to take? How complex is this test code going to be?
We are not QAs. We are developers. Our focus is not to "test for testing" but to "test for developing".
Let’s start cutting something off. As I’m using a serverless architecture, I can be pretty sure that the infrastructure is going to work. So, I don’t need to perform a real post over HTTP to be sure that my function is going to be triggered as expected. I can just call the Azure function directly by its class. This saves me the effort of discovering how I should bring up locally the Azure function to answer over HTTP.
I’m not owning the input format because it is coming from Telegram by a webhook. How can I acquire some input to test?
Have a look at the following code:

[FunctionName("HappyDarioBot")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(WebHookType = "genericJson")]HttpRequestMessage req, ILogger log)
{
    log.LogInformation("DarioBot was triggered!");
    string jsonContent = await req.Content.ReadAsStringAsync();
    log.LogInformation(jsonContent);
    
    return req.CreateResponse(HttpStatusCode.OK);
}
This is the first version of the bot.
After deserializing the content of the HTTP request, I log it. I deployed this on Azure, registered the webhook, and sent a message on Telegram to the bot. Then I went to the logs monitoring in Azure portal. There, I had my input sample. I copied and pasted it into the test and it's done. Repeat the process for every input type that you expect (and also for some unexpected form).

What about the output?

Simplify here as well. Usually, when it comes to testing a third-party API, you can’t check the state changes that your call triggered on their system. You rely on the fact that if API answers OK, then it's OK.
The same here. At this level of test, my definition of working is "the function answers OK". That’s all.
And the business logic? How do I know that it’s actually doing what I expect? With unit tests.
It’s quite trivial to spot that the business logic is going to be moved to a collaborator. The business logic must not depend on any infrastructure. That way, it’s easy to test it with unit tests.

Conclusion

I didn’t track how long it took me to develop the HappyDarioBot. However, I can estimate something between 25 and 30 hours in total. Some considerations:
  • I never developed something on Azure before.
  • I never developed a Telegram bot before.
  • I did most of the work one hour per day. This is not the same as 8 hours focused.
To wrap it all up, I want to say that as a first test of the serverless architecture I’m satisfied with the result. You have to learn how to use the tools of the platform, but as a developer, you can stay 100% focused on developing.
If you want to hit your target as soon as possible with a usable prototype/alpha version of your product, going serverless is an option that I suggest to consider. If you are a C# developer, then you will feel at home on Azure.

Tags

More by Luca Piccinelli

Topics of interest