Context
Yesterday, we released a new feature for our companyβs Slack App, written in Django (python).
So, while working on this feature, I also had to implement something which can convert currency code to currency symbol. For ex: INR β βΉ.
For this, I found a nice open source python library called forex-python. Among its other features, it also helps convert currency code to its symbol.
A utility function which I wrote
This function accepts one argument currency and expects it to have string value. For ex: βINRβ, βUSDβ, etc.
This class method c.get_symbol(currency) returns currency symbol as string. For ex: ββΉβ, β$", etc.
This function seems correct, right? Well, not completely.
Hereβs what happened next
Me about to merge my changes to master...
If this function works successfully as expected, it returns a nice clean currency symbol string.
Now, when I started to test the fail-safe mechanism of this function, thatβs when things started getting interesting.
Hereβs how I tested -
In case of passing wrong currency string to the function, I expected it to return back the currency string as it is.
But, it returned None. π€―
Then, I noticed that I didnβt receive any error logs.
Why didnβt I?This means that the except block never ran.
How could this be?This also tells us that if except block never ran, then this means try block ran successfully.
But, if this was the case, why didnβt I get the correct result?
Well, hereβs what actually happened -
Initially I assumed that c.get_symbol(currency) will return an exception if something goes wrong. I was wrong.
I checked the library codebase.
If a corresponding symbol is not found for a particular currency, then this method returns None, instead of an exception.
This was what went wrong. I wrote this whole fail-safe assuming that it would raise an exception. But it didnβt.
Finally, curr variable thus got assigned None value, which was what function was returning.
A Blunder. I know. π
Impact of this blunder
In case of this function failure, this is how it would have looked in the UI - βNone 1,234β. Instead, it should be displayed as ββΉ 1,234β.
This is not blocking the user. But, it would still be a UI/UX design issue.
This is how the product design team would have looked at me -
How did I fix it?
Just added a check - if curr is None, then return back the currency code string.
Key takeaways from all of this
Never assume anything.
Always make sure to checkout the codebase of external libraries.
Validate and test your changes quickly.
Write tests.
(Could have found this mistake in early stages if I already had a test for this)
P.S. If you are wondering about how did I upload these beautiful images of code-snippets, you can try out this awesome website called carbon.now.sh. Got to know about this from my colleague, Aiyush.
Put huge trust on open source but verify. :)
Guilty of the same! π