Тёмный

2 hours to build this!? Is TDD in Angular really worth it? 

Joshua Morony
Подписаться 77 тыс.
Просмотров 9 тыс.
50% 1

Опубликовано:

 

27 сен 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 33   
@JoshuaMorony
@JoshuaMorony Год назад
Join my mailing list for more exclusive content and access to the archive of my private tips of the week: mobirony.ck.page/4a331b9076
@_jn0298
@_jn0298 2 года назад
I have never done TDD because I'm relatively new to the Dev world, but I think the time you "waste" developing tests saves you from getting troubles in the future
@JoshuaMorony
@JoshuaMorony 2 года назад
Yep I agree with this, the payoff for tests is both in the future and for helping guide the architecture/development in general. Testing is something that can definitely take a long time to learn/do well though, and whilst you're learning they will probably cause you more grief than help.
@dinoscheidt
@dinoscheidt 2 года назад
@j Well it‘s a decision to always know that something will take two hours, or have the time saved today thrown at you compound into 2+ weeks half a year down the line. As soon it‘s clear that your code likely needs to still run in half a year, or was promised someone that it does, do TDD. But you‘re right: the weirdest part of TDD is that it feels silly in an empty repository. But glorious when you look a few sprints back.
@RichardPerfectKiwi
@RichardPerfectKiwi 2 года назад
You talk at the end of the video about how you have paid in full the technical debt of future changes, but I think you've skipped over the costs of "fragile" tests. The test code you have written will continue to break in all sorts of weird and unusual ways for the lifetime of your project. Sometimes that will be because of a genuine change in the functional code but something like 50% of the time the tests will break for all sorts of other reasons. The application code can be changed and achieve what the user wants, but the side effects of those changes will break the unit tests. From now until that code is permanently retired you should also count the number of times the tests need to be "fixed" but where the feature was "ok". The future cost of having 18 tests is not yet fully paid. Don't get me wrong, I do think Tests are important and valuable, these days I tend to think like some of the other comments the tricky bit is write the right tests at the right time. It's a goldilocks problem of not to much and not too little.
@JoshuaMorony
@JoshuaMorony 2 года назад
That's a good point and something I probably should have mentioned - there is going to be some maintenance of the tests required, and for poorly designed tests it's going to be a lot of additional work for probably little to no benefit. This is why I like a black box style approach to testing, as ideally I am testing the goal rather than a specific implementation, which means (ideally) the only time a test should need to be changed is if the actual requirement changed. It doesn't always work out that way, but I find I spend much less time fighting tests this way. With the specific TDD approach I mention in the video I find it also lends itself to creating the minimum set of tests required to actually verify the app does what it's supposed to do - somewhere near that goldilocks zone you mention.
@steellion907
@steellion907 2 года назад
I think that TDD is useful if you're... A ) creating a shared component or library that will be reused multiple places and by other developers B ) there is some sort of complicated calculations. Here, the tests are useful because you can definitively say things match spec. Outside of that I think TDD is unnecessary. Checking that "X component calls Y service and gets correct results" is unnecessary.
@JoshuaMorony
@JoshuaMorony 2 года назад
This is what I like about the specific TDD approach I outlined in the video - it forces me to create just enough tests to make sure the app is doing what it's supposed to be doing, with as few superfluous tests as possible. This might mean some rather simple tests are created (e.g. X calls Y) but only when that is going to be providing value in ensuring the software works - internal implementation details don't necessarily need to be tested. But if someone (or me) changes a button and accidentally forgets to add the click handler back in for that button, or a method is refactored and it's now missing an important call to some service, and now the application is going to be in a broken state then my goal is that my tests will always catch these scenarios. I don't think you have to use TDD to achieve that, but I find it to be the easiest way to create a suite of tests that strike a nice balance.
@Szergej33
@Szergej33 2 года назад
@@JoshuaMorony This, exactly right. When i'm working on a project from beginning to shipping it to the client, I know the codebase and I can make changes easily, keeping in mind all the areas affected by, for example, refactoring a method. But I work in small teams, and only a couple FE devs. As the codebase grows and othe people come in and make changes, I get pissed they make silly mistaeks bc they don't have the understanding of the codebase that I do. Ofc it is not their fault though, and tests can easily prevent that.
@pchasco
@pchasco 2 года назад
I’ve been a developer for 22 years. I do think unit tests can be a waste of time. I think unit tests make perfect sense for testing domain logic and services. I do not think there is sufficient ROI on testing UI - especially in Angular where testing UI code is agony.
@JoshuaMorony
@JoshuaMorony 2 года назад
I tend to mostly rely on Cypress for the template/UI testing, though I do still use Angular/TestBed for some UI testing when necessary. My main goal is just to make sure that if some feature isn't working, then some test will break. At least to the level I'm using Angular to test UI I don't generally find it painful (usually it's just checking if an element exists, or triggering an event handler on an element)
@dein-ding
@dein-ding Год назад
Are you planning on making more content on unit testing with angular and specifically with rxjs?
@JoshuaMorony
@JoshuaMorony Год назад
Yeah I have a few videos floating around the channel on testing/observables - I do intend to do more as well, though typically people don't seem to like those videos as much (probably just less people interested in testing) - any specific topics you want to see?
@dein-ding
@dein-ding Год назад
@@JoshuaMorony ooh thats great to hear, imma start digging then. I don’t have any specific topics regarding testing observables yet, I just recently started using rxjs in a more reified, reactive programming sense (because I came across your videos and was amazed by how clean complex logic could look like, great content btw, keep it up🤌) and I now need to start testing this as well. I get that testing related videos may not be as successful as non testing ones, I guess people are either afraid or sick of the topic 😆
@theanswer1993
@theanswer1993 2 года назад
Do you maybe have an example on how to E2E test write actions. Every time a test would be run you would end up with a new item in the list for example. So how would you then test that a list is empty for example. That test would only work the first time. Or maybe a more complex action where a post request updates some value on the other page and of you wanted to retest that you would have to reset the DB
@JoshuaMorony
@JoshuaMorony 2 года назад
Generally speaking, the approach is that you *do* reset everything between every test. For example, you would have local storage clear between tests, if you are using something like Firestore you would have your test DB (preferably emulated so it is quick/cheap) cleared between every test. Ideally, every test should get a clean slate (it shouldn't matter what order your tests run/any test should pass whether it runs first, second, or last)
@theanswer1993
@theanswer1993 2 года назад
@@JoshuaMorony Thank you for the quick response. And would that mean that if you started with a clean state and required an existing state for let's say testing the delete item action you would first run all tests that get you to that state or use mocks for that? A mock could be problematic I guess as it's not really an E2E test then, but preparing an initial state for each E2E is costly on performance.
@JoshuaMorony
@JoshuaMorony 2 года назад
@@theanswer1993 Definitely don't run tests to get you into the state you need to delete something - that would mean your tests need to run in a specific order to work, and if something happens with some other test it can potentially break your delete test. The order shouldn't matter, you should be able to run your delete test first and it will work. How you set this up will depend on your situation. You could just have your delete test go through the process of first adding an item and then deleting it, or you could manually trigger some code that will insert an item to delete at the beginning of the test, or you could have some "seed" data you use for your tests (i.e. at the beginning of all test there might be three items available: item one, item two, and item three - and the tests reset to this state at the beginning of each new test), and there are probably some other things you could do as well - mostly depends on the tech you are using.
@theanswer1993
@theanswer1993 2 года назад
@@JoshuaMorony Great thank you I will look into that. Maybe an idea for a video 😄
@davidontiveros2895
@davidontiveros2895 2 года назад
Awesome video Joshua (as always). Quick question. Have you had issues unit testing components that use OnPush strategy and marksForCheck to update view ?. Would be a great video 🤞 keep it up. Awesome work.
@JoshuaMorony
@JoshuaMorony 2 года назад
Yes so whenever I need to test inputs changing in a test that use OnPush change detection, I always just use the overrideComponent method in the beforeEach to manually change the changeDetection strategy back to Default. I find this a nicer solution than using markForCheck in the test.
@davidontiveros2895
@davidontiveros2895 2 года назад
@@JoshuaMorony I think I’m going to end up doing that. For a weird reason I keep having an unresolved timer after my test. Even after unsubscribing and don’t want to use the discardPeriodicTasks method since it feels like a nasty hack in my case. I suspect its because of a markForCheck I call within a subscription (in the component not the test) to update the view. Thanks for replying. Have a blessed one.
@J0Sh7
@J0Sh7 Год назад
@@JoshuaMorony How do you know that your code is working for OnPush strategy when you change it to Default in your tests?
@JoshuaMorony
@JoshuaMorony Год назад
@@J0Sh7 In this case I'm not testing whether the change detection strategy is working, I would catch this in higher level integration tests (i.e. my E2E tests) if there was something going wrong here
@davicampos802
@davicampos802 2 года назад
I Love tdd vídeos, Where can I find source code ?
@JoshuaMorony
@JoshuaMorony 2 года назад
The source code for this one isn't available at the moment but it probably will be in the future
@bidfca5980
@bidfca5980 Год назад
Source code please
@onetwothree123-
@onetwothree123- 5 месяцев назад
Many people avoid writing tests because they believe it speeds up feature delivery. While this can be true initially, in the long run, you'll end up spending much more time debugging and adding new features. Some realize this early on, while others don't. However, in enterprise applications, skipping tests can lead to hundreds of wasted hours and sleepless nights. Trust me, it's not a path you want to take. I could share countless compelling stories about this. The bottom line: write tests. Don't heed advice that dismisses their importance. You'll never regret it.
@rahff99
@rahff99 Год назад
It's not TDD at all, don't test view component, test your core logic only without knowing about the framework; TDD is not about testing nor E2E test nor view component test. this development method is a waste of time and it not a TDD, it's a test fisrt in bad design architecture.
@TomMcLellan1
@TomMcLellan1 2 года назад
That's a great chart on whether to choose pain up-front or later. For bootstrapping indie developers, or any other project where it doesn't make sense to invest in TDD at the beginning, at some point it likely makes sense to transition to automated testing (e.g. if the project/MVP is successful and/or you move towards a team approach to development). When moving an existing code base to automated testing, would you normally start with E2E/cypress or TDD? They're different animals and there's a learning curve for each, but I'd be curious of how you look at this for an existing code base (e.g. 25K to 50K LOC)... maybe the subject of a future video or course. It seems like both TDD and E2E deliver are valuable once a project/team reaches a certain size. It's too bad it doesn't work so well to add unit tests after the fact.
@JoshuaMorony
@JoshuaMorony 2 года назад
Disclaimer first: This is all highly opinionated and I don't think I have any particular authority to make claims here (I'm not Kent Beck lol) - I typically work alone and have developed a testing strategy that suits me. When I was working for startups we (surprise) weren't testing. The clients I work with today also typically aren't testing. So I've seen first hand the troubles I think not testing causes, but I don't have a ton of experience with larger companies who *are* testing and what troubles they might run into. I wouldn't make a distinction between TDD and E2E, I consider E2E tests to be the first step in my TDD process. I realise a lot of people, especially smaller indie/startups, will want that extra speed up front, but personally I feel like it's a trap to go with the "we'll add tests later" approach (a lot of the time later never comes). It seems like the decision is "We can't afford to do tests now, we need to get to market fast, we only have X amount of funds etc." but I think the thinking should be more like "We can't afford *not* to test now, because it will be too expensive in the future and we need the ability to remain flexible/fast". You don't want to find yourself in the position where you have a ton of tech debt/bugs in the codebase if things start taking off - this is likely going to be a time where you would want to push the dev efforts further with features etc. but you'll be bogged down with a less than optimal codebase. In my view, I think if you are building out any sort of prototype/proof of concept sort of things without testing (which is fine/makes sense) then once you have your PoC it should be rewritten from scratch with a testing strategy - only using the PoC as a reference. As for adding in tests after the fact - e.g. you already have an established codebase and are like "hey! we should really be testing", this is something I don't have much experience with and I'm not sure on the best strategy. An easy first step with quick wins is to add in E2E tests with Cypress, so I would advise writing out all of your main use cases/user stories, and write E2E tests to make sure they are covered. From there, you can probably start doing a retroactive TDD sort of approach - see what is required at a smaller/unit level at each step to make a particular E2E test pass. Break/remove that functionality, write the unit test to cover what it should do, then add the functionality back. It's going to be way harder after the fact though - since testing pushes you to architect in a way that makes it easier to test, an existing codebase is naturally going to be harder to test and might require large refactors. /wall of text over
@TomMcLellan1
@TomMcLellan1 2 года назад
@@JoshuaMorony Excellent perspective, thanks for that. From my reading, when working with an established codebase, you can start by having some code coverage standards for every new commit, and then gradually refactor the legacy / PoC code. For example Google's Testing Blog speaks of 60% code coverage as acceptable and 75% commendable, though also suggests that code coverage targets depend on the situation. That said, I can see how adding E2E/Cypress to the existing codebase delivers some immediate value, especially when scaled with browser / device testing (BrowserStack etc) as part of CI/CD. In some ways, the startup with the go-to-market focus is choosing tech debt over business/financial debt. Ultimately we should all strive to be debt free, because "move fast and break things" gets pretty tiresome. It does seem like both unit and e2e testing are key if you're taking a team approach, building for the long-term, and making ongoing changes.
@JoshuaMorony
@JoshuaMorony 2 года назад
​@@TomMcLellan1 Yeah the new standard moving forward + addressing existing code over time makes sense to me, though I would just generally rate a more culture oriented approach to testing, since code coverage statistics can be pretty meaningless and can effectively be "faked" with pointless tests that don't actually add to confidence in the code. Better to have devs buy into a philosophy around testing rather than trying to meet code coverage targets. And not to be too pedantic! But imo I think the choice seems like tech debt/work over business/financial debt (i.e. sure the code might not be "correct" but we save money), but really it's still taking on business/financial debt (I would classify tech debt and financial debt as the same thing), because without the testing strategy from the start you are going to be paying more for your development and taking longer a little down the road. So I would frame the no tests approach as save time now, but lose time and money later (because ultimately, you are likely to spend more developer/QA hours overall without a testing strategy).
Далее
Is reactive code with RxJS too hard to test?
12:57
Просмотров 9 тыс.
ngTemplateOutlet is WAY more useful than I realised
16:36
The easier way to code Angular apps
9:54
Просмотров 67 тыс.
RxJS made my code 5x shorter... but is it better?
12:48
Why use OnPush in Angular? Not for performance...
13:15
Being Competent With Coding Is More Fun
11:13
Просмотров 79 тыс.
TDD: The Bad Parts - Matt Parker
30:17
Просмотров 54 тыс.
Stop Writing So Many Tests
10:02
Просмотров 90 тыс.