5 ms·
The amount of people admitting not doing TDD surprises me. I wouldn’t dare to write any production code without a comprehensive suite of tests. Most projects I
by tobyhinloopen 6y ago
The amount of people admitting not doing TDD surprises me. I wouldn’t dare to write any production code without a comprehensive suite of tests.
Most projects I work on for have about 50% production code and 50% tests code, especially if I have a say in it. I simply won’t take any responsibility for my code if I cannot test it.
Funniest thing is that the projects that are well tested are also the projects that just work, rarely triggers the error notifier and rarely has bug reports. The errors that are present are usually due to 3rd party API outages, database outages or abuse.
- fareesh 6y agoI think TDD is a specific reference to the approach where you always write the test first, i.e. 100% coverage Could be wrong, but that's how I've always assumed it is intended.
- tobyhinloopen 6y agoYes that’s how I’m doing my daily job. Not sure if my apps have 100% coverage but I’m pretty sure it will be pretty close. Edit: I ran a coverage report on the app I’m working on and it’s 84% (4129 of 4936 LOC). Untested parts are related to deleted features, dead code or some weird error conditions I didn’t care to test. There are also some admin only related pages that are untested, and some stuff have their tests disabled because they directly communicate with production APIs because these services don’t have test apis
- fnord123 6y agoNot doing TDD isn't not testing. TDD is writing failing tests first and then writing the code to make the tests green (red, green, refactor).
- manmal 6y agoTDD != writing tests, but it means that you write tests before you code. Many people write tests for their production code, but they mostly add them after at least some of the code has been written. The idea is that you'll understand the problem space better by writing the test first. Which is IMO a valid assumption. But, at least for me, the problem space (interfaces etc.) is often a bit too fuzzy initially, such that it's easier to just write the first draft, and THEN test that.
- nickm12 6y agoThis! So many of the comments on this post are about writing tests, rather than writing tests first. I've tried TDD a couple of times and always hated it. Maybe it's one of those things where you have to get over the hump. But to me it's much more enjoyable to write what I think is the perfect function and then try to break it with my tests. I also don't understand how anyone could think that a strong typesystem is a replacement for tests. It definitely helps one write a lot fewer tests for the same level of quality, but you still need tests.
- tobyhinloopen 6y agoI know what TDD means. I write tests before I write my code. Usually I write out a set of tests (this should this X, Y and Z but not H, I, J) and then I implement whatever thing I need to add. Same with bug fixes or changes. Bug fix: reproduce in tests, then fix bug. Change: change or create new tests, then update code.
- regulation_d 6y ago> The amount of people admitting not doing TDD surprises me. I wouldn’t dare to write any production code without a comprehensive suite of tests. This suggests that you don't understand that people can achieve the stated goal of "a comprehensive suite of tests" without TDD. Just to be clear, people can be passionate about testing without being passionate about TDD.
- Chris2048 6y agoOr they can do testing, not do TDD, and be passionate about neither.
- tobyhinloopen 6y agoYou’re right: I don’t understand how people can have proper tests without TDD. I’ve yet to see a project with meaningful tests without TDD
- manmal 6y ago
- aroundtown 6y agoMy problem was learning how and why to do it. Most of the tutorials I've seen on the matter either test too trivially or too often. But it also says a lot about the places that I've worked where shipping code and carving out domain knowledge for job security was seen as more important that actually doing a good job.
- tobyhinloopen 6y agoI write tests in units of work. For example, If I need to add a contact form to a page, I’ll create a test that checks whether some form exists and matches some structure (names of fields) and I test that submitting the form performs some desired action. Usually I would replace the real mailer with a fake, test-specific mailer which has extra methods for keeping or inspecting sent mails. (There are libraries for this as well; it’s just an example). Testing the “real” mailer might never be done since it would involve checking if the mail was actually sent. In these cases I want to isolate that boundary so it is invoked as late as possible so I can use fake mailers for my tests. If the feature is mostly UI (like in this case) I usually test through the UI (using JSDOM and an HTTP client, or a virtual browser test runner like superagent). If the feature is more complex like an API or something, I like to write a barebones integration test (does this HTTP endpoint actually invoke some injected module) and then I thoroughly test the underlying module which is HTTP agnostic or represents bare minimum of HTTP state without dependencies to a real HTTP server or client. That way I can test the module without performing HTTP requests or mocking them. I usually start by writing lines like: - It returns no posts when there are no posts - It returns no deleted posts - After creating a post, posts index returns my post - Editing my posts updates my post - editing someone else’s post fails - deleting someone else’s post fails Once I’ve written the outline of my module like this, I convert them to empty tests and implement them one by one, first implementing a test, then changing the code to make the test succeed. Repeat until done. Usually I come up with more happy or unhappy cases while implementing - I instantly write a new blank test for later in these cases, adding it to the list of tests to write. I like to always have separate implementations for implementing features: one module for the business logic (which is thoroughly tested) and one for connecting it with libraries or frameworks or whatever (with minimum tests, but at least one). This is a guideline and not a requirement: sometimes a dependency to a framework or library or external service is just part of the feature so no point in keeping it separate.
- commandlinefan 6y ago> I wouldn’t dare to write any production code without a comprehensive suite of tests. If I'm starting from scratch, I always put together at-least decent code coverage. However, most of the time I'm not starting from scratch - I'm hired to work on a framework that's been around for a while and, invariably, is not only written without unit tests but written in a way that repels unit tests (every class depends on every other class, static initializers connect to live databases, etc.)
- rement 6y agoYou must not have inherited many ugly codebases. I would love to write tests for the codebase I currently work in but it just doesn't make sense. Everything works for the most part (not really but the business people are happy) so they is no way we can convince the hire ups that writing tests is beneficial.
- wenc 6y agoActually migrating legacy (ugly) codebases is where writing tests is helpful. The tests are the invariants -- they help you preserve functionality while you shift the code underneath. You can rewrite ugly code without worrying about botching anything downstream.
- nickm12 6y agoAgreed, but... often these ugly codebases are also very difficult to write tests for, because the code isn't well-factored, there are large functions which combine lots of unrelated behaviors, etc. etc. I inherited a codebase of this type two years ago. It was only 10k sloc of Python but some of the worst code I've ever worked with—of course it had no tests either. Retroactively writing tests for the existing code made no sense—half the behavior wasn't worth preserving. What I wound up doing was slowly refactor as I worked on things, writing a new component (with tests) and replacing bits of the legacy code. I also added linting and typechecking and now the code is not gorgeous, but it's serviceable and a lot less buggy. In retrospect it might have been better to just rewrite it from scratch, architected for testing, but it's difficult to be certain. I think it was probably better for the team to see the codebase improved piecemeal bit by bit, even if it took longer.
- wenc 6y agoI hear you. Testing is but one of many tools needed to fix ugly codebases. It's no panacea for sure.