I would like to ask about using Unit Testing in Web Development. The idea of Unit Testing is great but does it really bring value in the context of web application? Second part of my question is about TDD. If one creates an integration test before the actual code can this approach be called "Test Driven Development"?
1. Assumptions
By the definition Unit Test should test code on only one service layer. If a test tests code across multiple layers we have an integration test.
2. Argument
2.1 No Algorithms
There are not many algorithms in a Web Application. It's not like building a 3D Physics engine where every method does something challenging and hard to debug. Web application is mostly about integration and generating HTML.
The biggest challenges for a web application are: - clean code (universal problem for any software but not testable) - data consistency - integration (Programming Language, File System, Configuration Files, Web Server, Caching Systems, Database, Search Engine, External APIs - all those systems have to work together at a request)
If you want to build a Unit Test for every class in a web app you will be testing (in most cases): filling arrays, string concatenations and languages' native functions.
2.2 Cost
Just because a Web App is all about integration there are always multiple dependencies. You have to mock many different classes and writing even a small test might be actually a big job. What's even worse it's not only about test. Software needs to be testable. It means that one has to be able to inject dependencies in almost every class. It's not always possible to inject dependencies without creating additional layer between two classes (or systems). It complicates code and makes it more expensive to work with.
3. Integration Test
If web development is all about integration why not to test it? There are few counter arguments.
3.1 Integration test says "something is broken" but doesn't say where
That really comes down to: How much time does it take to find a bug when an integration test fails in comparison to time required for making code "UnitTestable" and more complicated (I guess this is subjective)? In my experience it never took long to find source of a problem.
3.2 You can run unit test on any environment, it's hard to do with an integration test
Yes, if you want to run integration test without a database. Usually there is a database. So long you operate on fix data and clean after each test then it should be fine. Transactional databases are perfect for this task. Open transaction, insert data, test, rollback.
3.3 Integration Tests are hard to maintain
I can't comment on that because all my test work well and I never had problem with that.
4. Create good Unit Tests!
The whole argument can be attacked with "If you create your Unit Test right, then you don't have any problems.". Can't that be the same with integration tests? If it's easier to create an integration test why not to stick with it and just make it right?
Don't get me wrong I'm not against Unit Test. It's perfect idea and I recommend to everybody. I'm trying to understand: does it really fit web development? I would like to hear you opinions and experience.
While unit tests always take results from a single unit, such as a function call, integration tests may aggregate results from various parts and sources. In an integration test, there is no need to mock away parts of the application. You can replace external systems, but the application works in an integrated way.
In unit testing, each module of the software is tested separately. In integration testing, all modules of the software are tested combined.
Integration tests should only verify that several components are working together as expected. Whether or not the logic of the individual components is accurate should be verified by unit tests.
Integration tests are harder to write. Unit tests can be run in any order, or even simultaneously. Integration tests usually required a strict order and can't be run simultaneously.
This is a damn good question, and one that more developers should be asking themselves.
I don't think this only applies to web development, but I think it's a good example to base the discussion on.
When deciding on your testing strategies, the points you raised are very valid. In a commercial world, cost (in terms of time) is likely the most important factor. I always follow some simple rules to keep my testing strategies realistic.
Once you've got these three points nailed, given your cost constraints you could potentially continue to test anything else that makes sense, in the way that makes sense.
Unit testing and integration testing aren't mutually exclusive, and unless you're building a beautifully unit testable library, you should do both.
The short answer is yes. Unit tests are valuable as are integration tests. Personally I'm not that good at doing TDD, but what I've noticed is that it greatly improves design because I have to think first and then code. That's invaluable, at least, for me but it also takes a lot of getting used to. This, I think, is the main reason to why it is so widely misunderstood.
Let's go through your points:
No Algorithms (but what you mean is few):
Well as stated in the comments, that depends on the application. This actually has nothing to do with TDD. Having few algorithms is not an argument to not test them. You may have several different cases with lots of different states. Wouldn't it be nice to know that they work as intended?
Cost
Sure it will cost, and if it is a small project, you might not get any value from TDD if you or your developers are new to it. Then again a small project might be just the thing to get started with it, so you are up to speed for the next, bigger project. This is a calculation you must do yourself. We are programmers, not economists.
Integration Test
Test that too!
Integration test says "something is broken" but doesn't say where
I'm sorry but I don't understand this one.
Hard to maintain
If it is hard to maintain you're doing it wrong. Write the test first, change the test before the implementation, when changing the code. Failing tests during development is a must for TDD. Actually don't quote me on that one, that is just my limited understanding of TDD.
I find this to be a very nice quote about unit-tests
Unit tests should be prescriptive, not descriptive. In other words, unit tests should define what your code is supposed to do, not illustrate after the fact what your code does.
What it boils down to is that integration tests and unit testing are two different things. TDD is a methodology for development, integration tests is more a validation of the application working as expected from a users vantage point.
Edit The community wiki says this about integration testing:
In an integration test, all input modules are modules that have already been unit tested. These modules are grouped in larger aggregates and integration tests (defined in an integration test plan) are applied to those aggregates. After a successful integration test, the integrated system is ready for system testing.
So actually my understanding of what integration testing
is was wrong from the start, but I don't think my answer is too far off except for the last paragraph.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With