What TDD Looks Like In A REAL PROJECT (With Code Examples)

Поделиться
HTML-код
  • Опубликовано: 8 янв 2025

Комментарии • 77

  • @ContinuousDelivery
    @ContinuousDelivery  Месяц назад +2

    🎓 Learn MORE about ATDD | FREE WEBINAR & ONLINE TRAINING - See below:
    FREE ATDD webinar: A hands on demonstration from me on ATDD practices ➡ courses.cd.training/courses/acceptance-testing-webinar
    Online Training: Dave Farley demonstrates the practices and techniques of a BDD-approach to Acceptance Testing. CHOOSE FROM 3 LEVELS THAT BEST SUIT YOUR NEEDS | Find out more ➡ courses.cd.training/pages/acceptance-testing

  • @phtrivier
    @phtrivier Месяц назад +23

    I don't understand why, but there is this weird "tradition" of explaning TDD by writing tests for... a test framework. Kent Beck even does that in canonical book. This is incredibly "meta", and terribly confusing at first.
    Why not come up with a more "real world" application as an example ? Something where the domain is simple enough that readers have a chance of knowing it ? (blog engine ? social media site ? basic accounting ? game rules ?)

  • @JobinJacobKavalam
    @JobinJacobKavalam Месяц назад +1

    Explaining the thought process is one of the hardest things to explain; you do it so well. Congratulations! Love it.

  • @craig2010a
    @craig2010a Месяц назад +15

    Only 19 tabs open? Those are rookie numbers!

    • @ohjelmistosuunittelijajoon6513
      @ohjelmistosuunittelijajoon6513 Месяц назад +1

      I once had a co-worker who had tens of tabs open in every program he used. I got burnt out only by watching him explaining something trough teams call.

    • @BestHKisDLM
      @BestHKisDLM 27 дней назад +1

      I have a colleague who only ever have two-three tabs open in browser and never more than one file in IDE scaled to 300% so he only sees 7-10 lines of code. My head explodes every time he calls because it takes 5 milion years for him to even find what he is trying to solve. 😂

  • @vaughncato
    @vaughncato Месяц назад +5

    The most important idea that I see in this video is that you don't need to write your tests to directly call the functions in the production code, but you can create a layer in-between the tests and the production code.
    I often hear the complaint that TDD doesn't work because if you decide to make a change to the interface, you have to go back and change all your tests. The DSL layer helps avoid that problem.

    • @Trezker
      @Trezker Месяц назад

      Ah! TDD people always say "don't test the implementation". To address the people complaining about changing test because the interface changes maybe they should also say "don't test the interface". It may be that TDD people think the interface is a part of the implementation but a lot of programmers think implementation only refers to what's behind the interface. It doesn't really change the amount of work you have to do, changing the interface still means you have to change the DSL layer. Though perhaps the DSL layer is also useful in other ways than just to facilitate testing, as a higher level interface that rarely changes.

    • @AndrewEddie
      @AndrewEddie Месяц назад

      The caveat, though, is that you have to write tests for the meat in the sandwich (which means directly testing directly using the DSL). This is the same problem with using fakes as test-doubles.

    • @vaughncato
      @vaughncato Месяц назад

      ​@@TrezkerHaving the DSL layer makes it where the changes you need to make due to a change in the interface is more localized. You may only need to change a few lines of the DSL layer, rather than a few lines of 100 tests.

    • @vaughncato
      @vaughncato Месяц назад

      ​@@AndrewEddieThe DSL is tested the same way the tests are tested, by seeing the test fail when the production code is wrong, and pass when it is right.

    • @AndrewEddie
      @AndrewEddie Месяц назад

      @@vaughncato that's correct, but that is "technically" in conflict with your original post (as I read it) where you are saying you don't need to test to directly call the code.
      That said, I personally I don't use DSLs at all for testing so I might be missing some nuance here.

  • @giovanelli93
    @giovanelli93 Месяц назад

    Great content! Even though it isn’t live code, it captures what TDD is about: changing our design as we write tests! It might sound a handful, we could end up with a lot of refactoring, but that’s good. The sooner you realize how much there is the faster you can either work it out or plan for the eventualities you’re going to face it

  • @juaneshberger9567
    @juaneshberger9567 Месяц назад +3

    awesome to see real world examples! also, I wanted to ask you, What do you think of the following approach: when you build prototypes or are just exploring is it ok to write minimal tests and just play around with what works not worrying about clean code, tdd, etc, and then once you have a proof of concept, using TDD and the other best practices to convert your prototype into production code?

    • @ContinuousDelivery
      @ContinuousDelivery  Месяц назад +5

      I think that's ok, but I tend to use TDD to explore with, because I think it makes things easier. I think that you should do whatever works for you when exploring new things, but you should do this as a "spike" and throw away any code you write when exploring, and then re-write it to production quality with full testing.

    • @juaneshberger9567
      @juaneshberger9567 Месяц назад +1

      @ContinuousDelivery thanks for the response!

  • @askarkalykov
    @askarkalykov 2 дня назад

    The elephant in all starter's TDD rooms is existence of old code uncovered by tests. How should the 2 universes interact? What lives on the boundary? How does it look like?

  • @marcotroster8247
    @marcotroster8247 Месяц назад +2

    Hi Dave, it's very interesting that you're only using strings and do the plumbing behind the scenes. I personally prefer to use hard-typed fluent apis with some kind of builder pattern to define my test cases in terms of the domain. For more complicated test cases I additionally enforce a strict order in which the api functions need to be called such that a non-technical person can produce valid test cases with IDE auto-complete. In my experience such tests are very readable in terms of the domain and aren't coupled to the implementation details because the ugly plumbing is abstracted inside the builders that can be easily replaced when needed. What do you think about this approach?

    • @bariole
      @bariole Месяц назад +1

      Unfortunately fluid apis are readable only by their authors. And if they have used them in last 3 months or so. It is quite obvious that mr. Farley is pursuing clarity of intention above all.

    • @ContinuousDelivery
      @ContinuousDelivery  Месяц назад +1

      I think it is fine, but for me the benefits don't outweigh the costs. It really is very team dependent I think.
      One advantage of strings for params that I like, is that non-technical, or at least less-technical, or even technical, people can invent new DSL on the fly as they are writing a new specification, without worrying about the design of the types to be used too much.

    • @marcotroster8247
      @marcotroster8247 Месяц назад

      @@ContinuousDelivery I agree. My fluent api approach is a bit too rigid for new development where the business rules might change a lot.
      In my case it's an untested legacy system with a established domain model that needs to be refactored. I need the fluent api to discover the domain anyways, so it's just a useful side product. We'll see if I keep the fluent api.
      For me, the more interesting part about acceptance testing is how to integrate non-technical people into the process, especially when the PO want to manually regression test all day long. It's kind of challenging to pull this agile transformation off on my own.

  • @valtergomes5808
    @valtergomes5808 Месяц назад

    Hi Mr. David!
    First of all, thanks a lot to share with us.
    TDD is a very controversial theme, due the discipline it requires and how the lack of such discipline leads to a messy and time consuming test suite.
    I have years of software developing, but still trying to grasp some nuances of TDD in a long term project, where discipline, caution and design can deteriorate in place of time-to-marketing.
    Please, I kindly ask you to dive deeper in this idea of DSL, WHY, WHEN, HOW.
    It's clear in the comments, it is not a usual concept, and a bit counter-intuitive (at least for me).
    Thank you in advance!

    • @ContinuousDelivery
      @ContinuousDelivery  Месяц назад

      You can learn more by following the links in the description to the video.
      You can seen an outline of the approach here: courses.cd.training/courses/acceptance-testing-webinar

  • @gerardguy9830
    @gerardguy9830 Месяц назад

    Love your t-shirt, it pretty much describes a part of my life !

  • @Anthonyfromtheuk-g3j
    @Anthonyfromtheuk-g3j Месяц назад

    I am a tester not a developer but have very similar concepts in our testing framework in particular the DSL and decoupling tests, what threw me in this video was the image showing the book name going in the db, you are using an actual db for unit tests? or tdd goes to higher levels than unit tests? Edit* Ok looking at the repo name yes its acceptance tests

    • @ContinuousDelivery
      @ContinuousDelivery  Месяц назад +1

      No, these were not unit tests, they were acceptance tests. The Unit tested code I showed is code that is intended to help to write these higher-level functional tests. So I am showing those tests for context really, though they are part of a broader TDD strategy.

  • @ratsock
    @ratsock Месяц назад

    11:00 You can you set the title using a uuid in the test scenario itself to avoid all this framework overhead. Tests can also decide for themselves when they need to be isolated or not. It’s an extra one line in the test, and significantly reduces the complexity of the test framework
    For default values I also prefer having the helper functions randomize inputs for the parameters I dont care about

    • @ContinuousDelivery
      @ContinuousDelivery  Месяц назад +1

      Yes you can, but now you put that complexity into the test instead. Sure, UUID works sometimes, I think this approach works a little better, since you have more control, for example, when you need to generate a name that will needs to fit into a certain number of characters, where a UUID would be too long, or where the name needs to meet some naming convention.

  • @judgewest2000
    @judgewest2000 Месяц назад

    I literally have no idea what my tests are called. I only write tests for functions that 'DO' something, like testing something that updates prices based on a percentage or whatever.
    This makes me make sure the 'DOING' part of a function (vs getting the data and saving it for example) is in a stateless function that can be tested on its own.

    • @ContinuousDelivery
      @ContinuousDelivery  Месяц назад

      You could also avoid writing functions that don"t "do something" 😉

    • @judgewest2000
      @judgewest2000 Месяц назад

      @@ContinuousDelivery That's not a useful comment. I'm talking about stuff like CRUD controllers. Code is needed for those to establish they exist. The parents have tests on them but not individual controllers.
      In a prior situation some have insisted they all have tests on them, literally no reason.

  • @AIPapersDecodedPodcast
    @AIPapersDecodedPodcast Месяц назад +2

    Hahaha, I love that shirt, it is exactly my life, which it is your advice for the quantity of RAM to get with the new Mini M4, 16gb, 24Gb or 32Gb?

    • @ContinuousDelivery
      @ContinuousDelivery  Месяц назад +1

      Usually best to get the most that you can afford, but it depends on what you are going to use it for. 16Gb is a lot if all you are doing is web-browsing, email & watching RUclips 😉

    • @AIPapersDecodedPodcast
      @AIPapersDecodedPodcast Месяц назад

      @@ContinuousDelivery I usually have also 30 tabs open, visual studio, some db client app, slack, teams, outlook and sometimes I open firefox to test something or run some automated test with chromium and sometimes, but not too often and just to play I open blender to do some boolean operations to some 3d objetcts and then after that I use chitubox to slice it. but of course more ram always is the better.

  • @Dorgrin
    @Dorgrin Месяц назад

    Love your work

  • @VaughnVernon
    @VaughnVernon Месяц назад

    The music is tinnitus from actual music played loudly decades ago. I friend told me so.

  • @SimGunther
    @SimGunther Месяц назад +4

    As some people rightfully called this out for "lack of real world examples", I don't think the problem is showing off any typing. It's more so the fact the code doesn't demonstrate sophisticated enough state management across a multitude of other classes and systems that typical code in real world projects have.
    Like, what is the decision making process to determine whether the interactions between classes matter more than just itemized unit testing? At what point does redoing system architecture make more sense with tools that validate architecture instead of implementation? What code analysis is needed to prompt conversations among devs + QA + product so the use case scenarios satisfy traditional vs unusual but real user interactions along with the prioritization to see why some things cannot be testable within a given timeframe? What truly qualifies as a known unknown vs unknowable unknown that would make testing more difficult than it should be? Market/socioeconomic pressures that fail to make testing like this unviable given arbitrary restrictions on staff just to appease members of the board?
    All this has to be factored in account and just saying "test more, duh. There's AI for that." is not helping on the conversation. Systematic thinking to make testing and conversation number one priority helps more than suggesting tools and "just test it". Software engineering is more human than we give it credit for being. 😊

    • @retagainez
      @retagainez Месяц назад +2

      Looked pretty real to me. The examples are simple like he explained, it's good design. You seem to gloss over the advice of NOT writing tests across multiple systems. That is bad code and bad test design! That part is tricky on purpose! But there are ways to mitigate those complexities

    • @SimGunther
      @SimGunther Месяц назад +1

      @retagainez Validating architecture is NOT testing across multiple systems. Each system tests their own capability using mocked data that would come from outside systems.
      Nice try with the strawman. ;)

    • @ContinuousDelivery
      @ContinuousDelivery  Месяц назад +3

      I think that you are looking at this from a testing perspective, which is completely understandable, but a mistake IMO.
      TDD is MUCH more about design, the tests are a nice side-effect of designing your code with TDD. You don't need to worry about what the scope of a test is, if you are using it to specify what you want your code to achieve, because the scope of the test will fall out from the need to specify. It may challenge your design thinking if the scope seems too large, but that is the primary point of TDD. To help you to achieve better designs.
      On your last point, "test more, duh. There's AI for that." I disagree, I think that this is another big mistake that the whole industry is making.
      What can an AI generated test test? If it is starting with a system, or even with the source code of a system. All it can do is confirm that the code does what the code already does. It can't test that the code does what the code is supposed to do. This is the same failure as after-the-fact unit testing which is dramatically lower quality testing than TDD and inevitably ends up fundamentally broken at the time when you need it to provide protection for your changes.

    • @tylerkropp4380
      @tylerkropp4380 Месяц назад +1

      A lot of the questions you have are not directly related to TDD. Many can take skill and experience to figure out. Others are a topic for another time. An experienced programmer will always be better at that than a novice, even when both use TDD. But compare them to their contemporaries who don't TDD and you'll see a massive difference in their output.

    • @SimGunther
      @SimGunther Месяц назад

      @tylerkropp4380 Like I said in the other comments and Dave implied in his courses/vids, TDD challenges assumptions about the system design and business model by way of tests. These business concerns interfere with TDD as a result because they're at the opposite end (release everything minimal cost) of engineers (deliberately release features that are carefully tested). Push back from the engineers is necessary or else they end up being "essential workers" insisting they work 100hr weeks without fail.

  • @timbouma6
    @timbouma6 Месяц назад

    live the t shirt! and the knowledge ofcourse ;)

  • @JanVerny
    @JanVerny Месяц назад +1

    I've tried to do TDD a few times now, but I always get stuck when trying to define tests without exploring the domain first. In the end after wasting a few hours I always just go back to iteratively creating the thing and then writing some validations of the solution I've settled on.
    What I think is the biggest thing that all the TDD preachers need to focus is on explaining the thought processes and how to reach the TDD mindset. Cause I just can't do it, seemingly no matter how many company hours I waste trying.

    • @ContinuousDelivery
      @ContinuousDelivery  Месяц назад

      That sounds like the topic of my first RUclips video...
      ruclips.net/video/xUi2951ufaw/видео.html

    • @vaughncato
      @vaughncato Месяц назад

      Hi @JanVerny
      Exploring the domain first is not a problem. It is called a "spike". Also, TDD is iterative just like you said.
      One thing that might help -- whenever you go to write actual production code, and not just a spike, go ahead and write one line and ask yourself, "what is an example of why I would need to have this one line of code?". Then comment out the line of code, and don't uncomment it until you have a test that fails because that line of code isn't there. If you have to refactor first before you can have a reasonably simple test, that's fine.
      I think this might help you see how having a test in place (slightly) before the production code is helpful when doing the implementation.

    • @JanVerny
      @JanVerny Месяц назад

      @@vaughncato This actually sounds like a good way to practice. I will try to see if I can reason backwards to what kind of test would result in a change I want to make.
      I am kind of skeptical of doing TDD and doing it iteratively. The way I see things, tests exist to put constraints on a system, and usually it's very easy to put more constraints on a system. But it tends to be very hard to replace one system with another when you have a lot of constraints in place.
      I suppose the TDD way would be to start by creating a new set of tests and a new system, but that sounds like a nightmare for an iterative process.

    • @ActualJosiahPreston
      @ActualJosiahPreston 19 часов назад

      You can do a lot of design work to explore the space by creating data structures and interfaces without implementations. You can then figure out what you are trying to do, and how the pieces should interact. Then once you have a good enough design, you start writing the tests, and only then start implementing concrete functions or classes.
      Trust the process.

  • @NicodemusT
    @NicodemusT Месяц назад +13

    While I don't always like Theo's takes, I respect that he codes live so you can see he's not just running from a perfectly repeatable script. I'm sorry, but this isn't really a real-world example. These are screenshots that you were comfortable posting. The majority of my feedback re: TDD on this channel is that you say "just do it", but have thus far not really shown how. Your video is an incomplete example of real-world testing. What I am finding is that the developers that keep telling me to do better rarely show their work, and humble developers are streaming their work and building a community.

    • @ContinuousDelivery
      @ContinuousDelivery  Месяц назад +9

      It is tough to decide how best to show this kind of thing, I assume that there is relatively little value in people watching me typing, at least when I am trying to show something in a short amount of time, as in a RUclips video. There are some "live" code examples in my TDD tutorial here: courses.cd.training/courses/tdd-tutorial

    • @Coburah
      @Coburah Месяц назад +8

      Did you mean to imply that Theo is humble? 😂 Or was your post just poorly phrased?

    • @xybersurfer
      @xybersurfer Месяц назад +4

      don't be silly. even live coding examples are biased in that it's an example that the author is comfortable showing

    • @Timelog88
      @Timelog88 Месяц назад +1

      ​@@mohamedtalaatharb2441 yeah that is a good playlist. James Shore is fairly underrated in his takes bu has some solid tales on testing (check his testing without mocks blog post). But I have to agree that I expected a bit more of this video, while watching someone typing is not necesarily interesting, the key part of TDD, thought proces and mindset, is imo best conveyed by showing it, instead of talking about it after the fact.

    • @NicodemusT
      @NicodemusT Месяц назад +1

      @@xybersurfer you're carrying water. I can find several RUclipsrs for you who are coding live, picking random topics during a stream. Don't be naive.

  • @bariole
    @bariole Месяц назад

    Firefox - switch to audible tab extension..

  • @Yulrag
    @Yulrag Месяц назад

    I still don't know how to use TDD for UI.API, sure, easy, but UI?

  • @nickbarton3191
    @nickbarton3191 Месяц назад

    The code examples are too small to read. You lost me.
    What you've said does resonate, persistence across tests are flaky, design it out so each test (suite) provides its own context, use Setup and Teardown.

    • @seNick7
      @seNick7 13 дней назад +1

      1. You can zoom the video.
      2. Setup and teardown should be avoided in unit tests.

    • @nickbarton3191
      @nickbarton3191 13 дней назад

      @seNick7 Why no. 2?
      When testing a component, doesn't it need a stand alone factory method to create it?

    • @seNick7
      @seNick7 13 дней назад

      @nickbarton3191 You can run setup as first call in each test. This way:
      1. You can tell exactly what is needed By looking on the test itself
      2. You avoid having setup that prepares each test in a bit different way, but in the same code. E.g. test D might not need 20% of the setup code in the [Setup], but it's hard to say which part exactly.
      These problems are described in books about unit testing,but I also have seen it in practice.
      PS. I use to setup the fixture in the Setup (ctor) method, but that's all. Fixture instance is used by all test so that's a compromise.

    • @nickbarton3191
      @nickbarton3191 13 дней назад

      @@seNick7 Don't think that I've ever needed unique set-up, different input conditions, sure.
      If set-up is called at the start if each test or in the framework set-up, well that's just semantics.
      When it comes to integration tests, of course the set-up is different, but they're segregated from the unit tests.
      Maybe we're talking at cross purposes.

  • @thevikas5743
    @thevikas5743 Месяц назад

    Already wasted my precious 1 min laughing out lout from reading the T shirt instead of what you are saying.