Test Driven Development in Ruby on Rails

Graduate of Le Wagon Ruby on Rails bootcamp in Lisbon. Learning TDD, and looking to know when and how to do it like a pro 🕶.
I'm a web developer since 2007, working mainly with Ruby and Javascript.
Follow this Taaalk

2 followers

854 views

Joshua Summers
11:38, 15 Jul 20
Hello Ricardo 👋
So before we get into the code-based details of testing, it would be great to talk about it at a conceptual, but practical, level first.
This means I don't want to know what the "best practice" is, or what is "theoretically possible", but how you really use testing.
So when you are actually building an application with TDD, in a general sense, how and when are you using tests?
Ricardo Otero
14:20, 15 Jul 20 (edit: 14:24, 15 Jul 20)
Hi Josh 👋
Sure, I know there's a lot of best practices on testing, specially when you're in the "Ruby world", but I don't know anyone that really follows those 😅
So, in theory, the "good practice" is to do TDD (Test Driven Development) for everything, which means you write your tests (all of them will fail) and then you start coding your application to make those tests pass.
You do this for small blocks in your app, say a model, a controller, etc., one at a time.
Joshua Summers
14:25, 15 Jul 20
And that's actually what you do? Or is that what you should do?
Ricardo Otero
14:28, 15 Jul 20
I do it in some specific scenarios. It's very hard for me (and I would say most people) to think ahead and know which methods, associations, inheritance, etc. a class will have to achieve a certain goal. For two reasons:
  1. You can achieve the same goal in a lot of different ways
  2. When you code you often refactor along the way, you start with a simple version and then change it right away because you see things can be done in a better way.
Ricardo Otero
14:30, 15 Jul 20
So, usually I start coding, small pieces of code, and for each small bit I create tests for it, after I'm happy with the code.
Often tests actually help me to refactor the code again! If the tests are hard to write it means that your code is not very good, so that's a big plus of testing everything in my opinion.
Joshua Summers
14:32, 15 Jul 20 (edit: 14:33, 15 Jul 20)
OK! And why is this:
If the tests are hard to write it means that your code is not very good
true?
Ricardo Otero
14:43, 15 Jul 20
Well, usually what I find a lot is that code that is too coupled together is harder to test. But sometimes that code could (should!) be separated. Imagine a Restaurant class, that represents a restaurant in your app. You may have a name method, and that's fine, it belongs to the restaurant. But you shouldn't have a chef_calendar  there, since it should be in the Chef class, associated with the restaurant. If you try to test this method you need to create a chef, with a calendar, but you're testing the restaurant, so you need to create associated models for every test.
In this example, the chef calendar logic will be harder to test when in the "restaurant scope", specially because you're creating instances (the restaurant) that are not needed for what you want to test. Probably we should have a Chef class and even maybe a ChefCalendar class. If you separate concerns (which is a good practice) tests are much easier to write. So one thing leads to the other, code that is well structured is easy to test.
If my code starts to be a pain to test I often think of ways to decouple things and by making the tests easier to write I often improve the code quality a lot!
Joshua Summers
16:20, 27 Jul 20
Right, I get you.
So as a relative newbie to testing it feels like everything and anything can be tested. Let's say you were making a basic chef rota app:

image.png 31 KB

What would be the first test you'd write and when? For example would you write a test before running:
$ rails g model restaurant name
?
Ricardo Otero
07:46, 31 Jul 20
I wouldn't, because that command will generate the classes for me, so it would avoid having tests failing because the classes don't exist :)
Ricardo Otero
07:50, 31 Jul 20
But I would probably write test right after that command. The models are usually easy to test, you can add tests to check some business logic (say that the restaurant name must follow some rules for example). Thinking ahead is the trick about TDD that is not always easy, but for simple things like this sometimes I end up doing it.
However, like I mentioned before, most of the times I just build the logic — restaurant class, validations, associations and additional methods — and then jump into the tests. Usually I do this one at a time, so I would do Restaurant first, then Chefs and then ChefRotas.
Joshua Summers
08:52, 31 Jul 20
Ok, so let's say we wanted to validate the presence of a Restaurant name, that would be the first test you write?
Ricardo Otero
12:21, 31 Jul 20
For example, yes 🙂
That's an easy one that you can test without "predicting" how the code will look like, because that's what you have to do a little bit when doing TDD.
Joshua Summers
12:35, 31 Jul 20
You have to predict what the code will look like?
Ricardo Otero
12:51, 31 Jul 20
Yes, since you're writing tests before the code exists (for "real" TDD) you need to know what code you'll have before writing it. Validations are often very easy to predict :)
Joshua Summers
12:57, 31 Jul 20
And what if you are working on something complex? If I'm doing something that isn't a standard CRUD, perhaps some complex business logic instead, I don't know how my code is going to look before I get lost in the problem.
Does that mean I'm not breaking my problems down enough? Or do you handle things differently when you are working on something non standard?
Follow this Taaalk

2 followers

854 views

Start your own Taaalk, leave your details or meet someone to Taaalk with.