Unpopular Opinion: TDD is Fine. But It’s Not Beginner Friendly? You Sure?

Hocky Yudhiono
8 min readMar 14, 2022

--

Hi everyone! Today, I’m going to talk about Test Driven Development. It’s an approach on how to code in a n̶o̶n̶-̶s̶e̶n̶s̶e̶ a̶n̶d̶ c̶o̶u̶n̶t̶e̶r̶i̶n̶t̶u̶i̶t̶i̶v̶e̶ good way!

It was developed by Mr. Kent Beck in the late 90s. Software engineer before 1998:

No, seriously. Basically you have to follow these steps:

  • Write a test for the next function you want to add (RED)
  • Write the code itself until the test passes (GREEN)
  • Refactor both of them to make it well structured (REFACTOR)

This practice was forced (should be encouraged though, IMO. So sad.) throughout my software engineering project course, and it’s driving student mad, because it’s just a very weird way to code 😭.

Denial

So some of my friends started to do it in a very bad manner, that is:

  • Write the code first
  • Test it in local
  • Write the test
  • Commit the test as (RED)
  • Commit the code (GREEN)
  • Refactor the code (REFACTOR)

Anger

I was kinda sad because of this, I have just learned react js in less than 2 weeks (in total), and this is my first time doing react native. I’m not really good at front end. I only know basic competitive programming that I hope it can help me goes through this. I’m so mad at the decision about TDD is a must. It’s not OK for me. So I decided to write out all my problems here 😡.

I Don’t Use it in a Daily Basis, and “No One” Really Does

I did a poll in linkedin just to show how much I hated TDD.

OK, this is so biased and I’m sure I couldn’t base my hatred because my linkedin networks are dominated by students. I watched some videos on Youtube

Your Linter Doesn’t Agree With You

When you’re creating tests first, you’re writing classes that you don’t know exist, mocking modules that you don’t know exist. TDD in Javascript is a nightmare, moreover if you’ve just learned React Native, for 2 days, and your TDD grade is at the edge of the deadline.

Baby Step, Giant Step

When you’re learning a new framework. You must not start TDD directly! You must be familiar with the framework, you must know how to test your code, you must know what design pattern is for your code.

That is one thing that I kinda don’t like in my software engineering project course, they’re enforcing something that needs time to learn.

Bargaining: What People Don’t Tell Us About TDD

So, what to do now? I’m gonna admit, I did the stupid denial move like what I described above, for the first week. I know this is not a good practice, this is hurting myself from the inside. I was thinking of learning TDD properly. As in properly, I have to read the original book written by Kent Beck himself.

Kent Beck is Familiar with The Testing Unit

He knows how to work with JUnit, he’s already experienced in writing tests, he writes test using his “muscle memory”, he knows how to mock stuffs. While some of the students, don’t even know what mocking is.

What actually requires a lot of time is learning/mastering TDD as well as understanding how to set up and use a testing environment. When you are familiar with the testing tools and the TDD technique, it actually doesn’t require more time. On the contrary, it helps keep a project as simple as possible and thus saves time.

References:

TDD Was Made For A Better Code Design

In a sense, TDD was kinda approached in a black-box manner, so you call a function and try to check out what it outputs, it should match the expectation. If you’re lacking of code design knowledge, I don’t think TDD is for you. By doing TDD, you have to design the code first, rather than code it in one place, and refactor it in a better way next time.

TDD Was Made For A Reminder For You To Focus and Write Tests

I think the reason for this is that working in a test-driven development style gives you this sense of keeping just one ball in the air at once, so you can concentrate on that ball properly and do a really good job with it.

In a sense, do your code one by one, after one part is done, don’t forget to write test in there to make sure when you’re changing something, the part will still work

It’s not “I Fear Because of TDD”, it’s “I Don’t Fear Because of TDD”

Just like parenting, enforcing TDD practice is bad. All religions teach us not to force someone to believe something. If you don’t want to do it, you may encourage them, show them it’s worth it. Not forcing it! After all, like an Indonesian phrase says

Cinta Adalah Perkara Menerima, Bukan Karena Dipaksa

TDD was made to guide you to know the bigger picture of what you’re designing. As quoted from the TDD book:

Test-driven development is a way of managing fear during programming. TDD isn’t an absolute the way that XP is. XP says, “Here are things you must be able to do to be prepared to evolve further.”

Quoting again:

TDD is a little fuzzier. TDD is an awareness of the gap between decision and feedback during programming, and techniques to control that gap. “What if I do a paper design for a week, then test-drive the code? Is that TDD?” Sure, it’s TDD. You were aware of the gap between decision and feedback, and you controlled the gap deliberately.

Test here, mostly is code. But there are now many styles of TDD. Thinking your system architecture thoroughly, is part of TDD as well! So be courageous! Don’t let grades and courses make you hate TDD!

Testing Views?

Testing views can be quite tricky, if there are less logic, you may want to spare them using TDD. Because TDD is mostly made to handle functional logics.

Depression

For the first week, I learned TDD on my project code. Here is the full example I’m going to explain on what 12 hours of stackoverflow masterpiece I gathered:

describe(name: string, testFunction: ()=>void) is used to wrap all of your tests, inside there should be the tests. In javascript, the mocking is quite easy, you can use the spyOn and mockReturnValue methods. There are several others that you can check, like for example mock function with parameter, etc.

Next, you’ll have just to find the components, and simulate pressing it. You can use the fireEvent class if you're using react-native-testing-library. And that's all.

Testing UI is so easy!

Acceptance

Well, now I’m quite familiar with TDD, now I can easily use it by now in my daily commits!

More on Testing

When testing softwares, we can separate this into two parts, functional testing and non functional testing. Functional testing basically tests whether your software runs correctly or not 🏃‍♀️. While non functional is more on how good the performance is, is it secure enough? and so on.

In functional testing, sometimes we know the term of black box testing and white box testing.

Black box testing is relatively easy, let’s say you have a function to run. Let’s say the signature is like this.

function isCamelCase(s : string);

black box testing is like, you prepare the input for lots and lots of possible string s, and you check whether the output is correct, even though you don’t know what the inside implementation was like. 🖤

Different with the white box testing. In white box testing you sometimes will check the inside working of the function, are all of them mocked correctly, are the camel case function calling some certain functions, and so on. 🤍

In my project, I used white box testing and black box as well, just to make sure the programs run through a good logic progress.

Now, I’ll put some testing category that you should at least have a glimpse of. But yes, I’ll show you in the terms of “React Native” Point of View.

  • Unit testing, testing the functionality of a certain scope. In front end project like mine, this is quite tricky. We use this when checking the logic business function and the screen function, whether each components renders correctly, each button pressed results in a good stuff 🍎.
  • Integration testing, testing the integration and the relationship between two or more units in a system. In my project, I use this when checking the relationship between the components are correct or not, are the navigations of two screens are running correctly 🍍.
  • System testing, this evaluates a system in full running environment, we did this every several big merge request just to check on the flow, whether it runs correctly or not. Like when the time Eko found a bug on the confirmation screen can results on two mnemonic phrase being shown twice, the button will broke. This is one of the bug that system testing can caught 🐛.
  • Acceptance testing, this sometimes collides with unit testing, but more on a high level. User acceptance testing is also one of it. Does it being done automatically by code? Not really, it shall be performed by human. We also did this 🍊.
  • Performance testing, here it can be kinda relative we do performance testing manually by pressing the buttons several times, check whether it lags or not, whether there are memory leaks or not 🍐.
  • Security testing, this can be done in the developer system in the react native environment, we should check whether the js components render correctly, not showing any important URLs, data or something that can lead to data breach in our system 🍒.

There are a lot more of other testing you can do, those I mentioned just one of the testing you can do in a project! See you!

--

--

Hocky Yudhiono

Fullstack Developer 💻, Competitive Programmer 🐭, Blogger 📝, Eager Learner 💤 | https://hocky.id/