Spyros
Spyros

Reputation: 48666

Why doesn't RSpec enforce behaviour?

I understand that rspec is used to test with specific examples, but it seems to me that errors most times are of dynamic nature. Therefore, i'm having some doubts if unit testing is really useful for me ( i don't say that rspec is not useful of course).

I'm thinking that if i add a validation on a model, this enforces its behaviour. Since i already know that i will put it, what is the real point behind creating a test for it first ? After all, it will always pass if i don't change the validation (in which case i will notice of course). Provided that i'm the only developer, isn't that a little bit too much work for no real reason ?

Moreover, let's say that i have a test that specifies that user.name must be either 'Tom' or 'John'. My tests work great, because i specify user.name inside the test. However, in the real application, it may happen that name becomes 'Alex'. Rspec would not be able to enforce the behaviour, would it ?

And i would be left with a passing test, but an error.

What do you think about all that ? Are my concerns correct or i am not thinking it well ? I need to know whether i would get some strong benefits from messing with rspec, or it would mostly be a waste of time.

(Again i understand that rspec can be useful, but what about the matters that i specify here ?)

Upvotes: 1

Views: 128

Answers (3)

Jonah
Jonah

Reputation: 17958

I'm thinking that if i add a validation on a model, this enforces its behaviour.

Adding validation to your model gives that model some behavior but does not enforce it. A behavior is only required when some other piece of code depends on it and will break if it changes. Until a behavior is used removing it would have no impact on your project and so nothing enforces that the behavior must be present.

Since i already know that i will put it, what is the real point behind creating a test for it first ? After all, it will always pass if i don't change the validation (in which case i will notice of course).

Writing tests, especially writing tests first, gives you an immediate use of your code. Something which requires a behavior to be present and which should fail quickly, reliably, and automatically if that behavior changes. Tests enforce the public interface to your code because otherwise you will change that interface and you will not notice.

Provided that i'm the only developer, isn't that a little bit too much work for no real reason ?

You may be the only person working on the project but you can't remember everything. Write tests so that next week you have something to make sure you don't violate the assumptions you made today.

Moreover, let's say that i have a test that specifies that user.name must be either 'Tom' or 'John'.

That is not specific enough to be a good test. You can test that "a user should be valid when user.name is 'Tom'" or "user.name must be included in ['Tom', 'John']" or even "a user should be invalid if user.name is 'Alex'". You cannot hope to write a test for all possible inputs to your application so you need to make intelligent choices about what to test. Test that valid inputs produce valid results. Test that invalid inputs fail in expected ways. Don't worry about testing all possible invalid inputs or invalid uses of your code.

If it is not valid for "user.name" to be "Alex" then perhaps you should test that the code calling your User object does not try to set its name to "Alex". If "Alex" is a valid name but your code failed anyway then you should write more robust code, better tests, and a test for the name "Alex" to make sure you fixed your User class to handle that name.

Perhaps most importantly, if you are writing tests first then they can actually drive you to design a better interface for your User class. One which more clearly expresses the behavior of the "name" attribute and discourages you from setting invalid names.

Upvotes: 1

rubyprince
rubyprince

Reputation: 17803

Test cases, in my opinion, are sort of like documenting the requirements. We ensure that these requirements are met when we pass the tests. The first time it wont make sense, as we will be writing the code with requirements on mind. It is when we have to change code to incorporate something else also (or just refractor the code for performance), the tests really come into play. This time, we have to ensure that the previous requirements are also met while making the change i.e. the test cases do not fail. This way, by having tests, we are making a note of the requirements and making sure the requirements are met, when we are changing or refractor the code.

Upvotes: 1

coreyward
coreyward

Reputation: 80070

Tests are tests. They test things. They don't enforce things.

They are useful because you can see what is and isn't working in your application. When you override that name= setter to do something fancy and it breaks on a simple case that you had written a test for, that test just saved your ass. For simple cases like this, going without a test might be okay. It's really rare that you see 100% test coverage in non-open-source applications. Until you learn what you don't need to test, though, it's easier to just write tests for everything you can.

If you don't understand Test Driven Development or why you would test, I think you should Google around on the subject a bit and you can get a good taste of what there is out there and why you should use it (and you should).

Upvotes: 1

Related Questions