Testing

Testing Randomness

Testing Randomness

by Jakub Rodzik

In the talk titled 'Testing Randomness' presented by Jakub Rodzik at the wroc_love.rb 2023 event, the speaker explores the challenges faced when testing for randomness in software development. The central narrative follows a character named Fredo, who is tasked with creating a simple game involving dice rolls for two players. The purpose of this adventure is to illustrate the importance of implementing proper testing practices, particularly Test-Driven Development (TDD). The presentation is structured around key points that demonstrate both the practicalities and pitfalls of testing randomness.

Key Points:
- Introduction of the Hero: The story introduces Fredo, a developer faced with the challenge of building a game that returns a winner based on dice rolls, setting the stage for his programming journey.
- TDD Focus: Fredo starts his development with tests, adhering to TDD principles, to validate the game's logic before implementation. He first writes tests to ensure the game can correctly determine a winner.
- Challenges with Randomness: The narrative highlights the complications of testing scenarios that rely on randomness. When new requirements (like handling ties) are added, Fredo discovers that the randomness makes it challenging to validate outcomes with certainty.
- Introduction of Mocks/Stubs: To overcome testing obstacles, Fredo's fellow developers suggest using mocks and stubs, allowing the testing of all game scenarios without relying on true randomness, emphasizing that predictable outputs lead to reliable tests.
- Refactoring for Better Design: The talk illustrates the application of SOLID principles, specifically the Open/Closed Principle, and introduces abstractions like a Die class to improve code structure. This allows different types of dice to be implemented without altering existing tests.
- Event Logging for Transparency: To address customer feedback regarding game outcomes, the presentation simplifies tracking events in the game, providing logs that detailed the gameplay and outcomes.
- Final Conclusions on Testing Randomness: The talk concludes by advising against testing randomness directly. Instead, Rodzik suggests extracting randomness where possible and controlling it to ensure reliable outcomes in tests.

With these insights into Fredo's journey, Jakub Rodzik effectively conveys the complexities of testing randomness in software and reinforces the importance of structured testing methodologies and code design principles.

00:00:04.259 Thank you. So from what I've heard, I'm replacing a guy who's supposed to be tall and good-looking.
00:00:10.920 Jokes on you, huh? All right, I think we can start.
00:00:18.539 Today, I'm going to tell you a story. I know some of you might be tired already.
00:00:23.760 So you can treat this as a bedtime story. This story will be about an adventure.
00:00:31.080 As in any good adventure, there should be a hero, and our story will have a hero as well.
00:00:38.880 Our hero will face a lot of challenges to answer one question: how to test something that's random.
00:00:46.620 So let's keep our fingers crossed for our hero. Hopefully, he will learn something.
00:00:52.739 And hopefully, some of you will learn something as well—or at least have some fun. Let's start.
00:00:59.100 Meet Fredo. Fredo might look familiar to some of you because, just like most of you, he is a developer.
00:01:07.080 So it's natural that you can see some parts of yourself in Fredo. He will go on an adventure.
00:01:13.080 Now, what's the adventure about? Fredo has to write a game.
00:01:23.220 A game that takes two players. Each player rolls a die, and if the first player rolls a better score, he wins. Otherwise, the second player wins.
00:01:29.460 Sounds simple enough, right? Now is the time when we can try to look through Fredo's eyes and implement this ourselves.
00:01:35.520 We started with a Game class and with tests. Where do we start? Of course, with tests.
00:01:41.960 Let's get started. Oh, by the way, those are in our specs, so you probably all are familiar with it.
00:01:49.560 Our game should return a winner, right? So we want to have a game, which we will call Game.
00:01:55.440 It should take two players. Let's call them P1 and maybe Miri.
00:02:03.379 Right. We want to have a play method. Now the fun part begins because we expect this game to have a winner.
00:02:10.520 But it shouldn't be just typing P1 or Miri all the time. This thing puzzles Fredo further.
00:02:18.840 He's very pragmatic and doesn't let these tiny details stop him. He writes the code according to the business requirements.
00:02:24.540 If game P1's score is greater than game P2's score, P1 wins. Otherwise, it's Miri.
00:02:31.200 Sounds simple enough, looks simple enough. Let's see if our tests tell us something.
00:02:37.739 The main thing you have to look for here is: are the tests red or are they green? This time, it's red, which means it's good.
00:02:43.620 We also wrote tests that are not covered. There's nothing here; they fail. It's perfect!
00:02:50.640 Let's try to write some implementation now. Initialize, we take P1 and P2, of course.
00:02:56.880 We want them to have a play method.
00:03:04.860 This should involve a result of a dice roll, so let's say one to six.
00:03:10.620 We've all seen dice before. Six sides from one to six. Our main logic here is this:
00:03:18.540 If P1's score is greater, P1 wins; else, it’s P2.
00:03:24.540 All right, and let's see if our tests will work. Only one more thing: attribute readers.
00:03:30.180 All right, let’s run some tests now.
00:03:36.300 Look at that! Everything is green. Everything is perfect. Fredo is very happy with his code.
00:03:42.000 Not only did we solve the problem; we wrote tests first. This means it has to be TDD.
00:03:49.560 Only one thing left: we have to let the world know, so let’s go on LinkedIn.
00:03:55.440 TDD—it's there! The company earns a ton of money, and we want some improvements.
00:04:02.500 Right now, we have validated our idea; it’s great, fantastic! We need some more.
00:04:10.920 So we have a new quest here: let’s add a draw. Right now, well, it’s only one under the other.
00:04:21.539 But sometimes both players can roll the same number. It’s supposed to be a tie.
00:04:29.520 That doesn’t sound that bad, right?
00:04:36.600 So let’s go back to the code and see what we can do here.
00:04:43.260 First of all, where do we start? With tests, right? We already have those beautiful tests here.
00:04:52.380 So let’s try to modify them. We have our else branch; let’s change it to else if P1 score equals P2 score.
00:04:59.640 Perfect. And one more thing: else it’s supposed to be a tie. That’s fine. Now let’s run some tests.
00:05:10.260 The first thing that was unexpected happens: we just added a new requirement to our tests.
00:05:17.400 I think at least Fredo thinks he did, and the tests still pass. How is this possible?
00:05:26.480 Fredo has a group of friends, very close friends—one might even say a fellowship.
00:05:33.180 But he asked for their help. I don’t have Fredo’s friends here, but I have you guys.
00:05:40.780 So let’s start. What’s wrong with this test? It’s obvious.
00:05:47.320 Yes, they are random. Yeah, that’s true. But in this specific scenario, what do you think could be improved? Why did the test pass?
00:05:55.680 Come on, I know you know it’s not that late. Of course, because we have those if statements here, the result is that only one of those test branches is run at a time.
00:06:07.259 This is not what we’re looking for because we either test if Pepin was a winner or Miri, but we never test all of those branches at once.
00:06:14.600 All right, now what do we do? Let’s go back to the state with the code that we thought was working.
00:06:22.440 Let’s remove this additional requirement here.
00:06:28.800 Okay, so what can we do to actually make those tests better? Any ideas? We want to get rid of if-else statements.
00:06:35.639 So what can we do? Come on. Monkey patched around? How would we achieve that?
00:06:42.480 Yeah, down the rabbit hole? No, no. Okay, any simpler ideas?
00:06:48.600 Oh yeah, I can hear something. I think Fredo would love that. That’s true—let’s begin with stubs or mocks.
00:06:55.620 Fredo, as an experienced developer, is quite familiar with that.
00:07:02.480 So we go here, our spec, stub branch.
00:07:09.120 Stop front. All right, it gives us hope because it looks like someone else was looking for that as well.
00:07:16.740 There’s a question that looks like maybe it might be about the same thing.
00:07:23.640 There’s like an answer, but it’s a bit too long. So whatever.
00:07:30.780 Oh, look at this one-liner! That’s nice. Six subvotes—that’s even nicer.
00:07:38.040 Okay, copy-paste. Like it has to be good, right?
00:07:44.460 All right, let’s type it here. I will show you the full line.
00:07:51.960 So it’s allowed to receive random and return one, two, three, four, five.
00:07:57.480 We actually want to update it a bit, right? Three, then one.
00:08:04.320 This means that the first time we call random, it returns three; the second time, it returns one.
00:08:10.800 And this means that we should be able to get rid of those.
00:08:16.560 But to make sure that we didn’t break anything, let’s run tests. They should pass.
00:08:23.960 Perfect! Now we have a test that always tests the first branch here in line 13.
00:08:30.600 The only thing left is to write another one that returns Miri.
00:08:36.300 Yeah, thanks Copilot. Let’s run it.
00:08:43.260 Now we have two examples. Both of them pass and look much more reliable than what we used to have.
00:08:51.600 Okay, now time for the new requirement.
00:08:57.600 It returns a tie.
00:09:04.320 Okay, in case we have three and three, we want a tie. Let’s run some tests.
00:09:10.320 They are red, as we expected.
00:09:16.920 So the only thing left is to update the code itself, right?
00:09:24.480 Okay, let’s run some tests.
00:09:30.480 Outstanding! Fredo is very happy.
00:09:37.680 He has become like a company hero right now.
00:09:44.640 Of course, something we have to include in our city.
00:09:50.940 Now we're starting to see other companies pursuing our success.
00:09:57.480 There are a lot of companies that want to make the same amount of money that we do.
00:10:05.760 But fear not! Our business is prepared for that.
00:10:11.760 We know how to be one step ahead of our competitors.
00:10:18.240 You might say this is a revolutionary idea.
00:10:23.520 We’re going to use a new die, but we don’t call it new; we call it the better die.
00:10:30.360 Previously, the old boring die only had scores from one to six. Our new one will have one, one, three, four, five, and six.
00:10:40.200 Well, it sounds simple, although Fredo is not convinced. It’s like a revolution.
00:10:47.280 But the ticket is already in Gerard, so why not?
00:10:54.480 Back to code then. Fredo takes a quick look at what he already has here.
00:11:00.720 He notices one thing: we actually don’t change any of the logic.
00:11:06.120 It stays the same—basically, we shouldn’t change tests as well.
00:11:11.640 The only thing that’s left is to change the code that represents the dice roll.
00:11:19.440 This is what was changed, so maybe we could do something like one, one, three, four, five, and six.
00:11:25.920 And dot sample. It’s simple enough.
00:11:32.160 This is what we want. Note two here; it’s only one.
00:11:40.800 We should be good here. So you probably already know what will happen when I run these tests.
00:11:48.480 Yeah, Fredo is about to find out. Red everywhere!
00:11:55.080 Fredo’s face is getting red as well because we were supposed to do TDD.
00:12:01.680 Sorry, it was all supposed to be beautiful, easy, and fun.
00:12:08.640 Whenever we get a new requirement, it goes down.
00:12:14.640 Tests are always red! It would be best to remove them, but we probably wouldn’t get approval on GitHub.
00:12:21.720 So, we have to do something about them.
00:12:29.520 First thing’s first: let’s get back to the version that we know was working—the one with front.
00:12:36.480 So, what can we do now? Fredo asks his friends about this, and they tell him one thing: SOLID.
00:12:43.440 Yeah, Fredo knows about SOLID a thing or two, especially about the O.
00:12:48.480 Because O was his favorite letter—the most round one. He remembers what it stands for: Open/Closed Principle.
00:12:56.640 The idea is that maybe this could somehow help Fredo as well.
00:13:02.880 The other thing is he notices that although the game appears to require rolling a die, we don't actually have a die anywhere in the code.
00:13:09.540 The lines from 9 and 10 should represent this better. Therefore, let's introduce an abstraction we can call a die.
00:13:16.800 Let’s do that.
00:13:22.560 That’s called die. It should return the same range from one to six.
00:13:28.260 Okay, let’s try to include this in our class: die.new. Of course, attribute reader.
00:13:34.680 And what we need to have here is also a variable.
00:13:41.520 All right, before we do anything else, let’s make sure we didn’t break anything. Tests are still green.
00:13:48.480 Let’s try now to include this abstraction here.
00:13:55.920 Awesome! Tests are still green, which means we actually did a proper refactor here.
00:14:02.040 Nothing has changed, aside from the implementation. The behavior stayed the same; that’s good.
00:14:08.940 However, how did this help us? We still have a die that rolls randomly.
00:14:15.480 However, if we could somehow create a machine-dice that rolls in a very specific way, we could use it in our tests.
00:14:22.320 Because if we know it always rolls one, we could test for a tie.
00:14:29.280 So let’s see if Fredo is able to somehow machine this die here.
00:14:35.520 We can call it fake die. Now we want to be able to define those rolls on the go.
00:14:46.560 Of course, it has to have a method roll.
00:14:53.520 I think it’s called die typing, right? If it looks like a die and rolls like a die, it’s a die.
00:15:00.840 Okay, let’s see if we can somehow include this fake die in our tests.
00:15:06.960 Maybe we can create a die. It’s a fake die. Okay, let’s include it here.
00:15:13.680 Let’s run our tests. Nothing has changed, which is good.
00:15:19.800 Now, if our assumption is correct, we should be able to remove this line.
00:15:26.160 Let’s see what happens now. It still works! Great!
00:15:32.640 Now let’s just do this for the rest of the examples: one, three, and here we want one and one.
00:15:39.120 Let’s remove those lines; we don’t need stubs anymore.
00:15:45.600 I had to, of course, forget about passing the dice.
00:15:52.680 Okay.
00:15:59.520 Perfect! We’re still in the very beginning, meaning everything works kind of as it used to.
00:16:06.600 But there is still one more important thing here.
00:16:13.920 Our class that we were testing no longer cares about the die and the type of die.
00:16:20.880 It only cares that it rolls. So to achieve our goal, we have to do one more thing.
00:16:26.520 Remember how we called it? It’s better die. Nothing nice.
00:16:32.700 Here we implement sample.
00:16:39.240 All right, now we replace this old boring die with better die.
00:16:46.860 Let’s run tests. Tests are still green!
00:16:50.520 Because we don’t really care about the die anymore; we only care that it works.
00:16:55.320 We test what we have here. Perfect.
00:17:01.680 You probably know what this is called. If you don't, you can follow Fredo on LinkedIn.
00:17:06.960 It's called dependency injection.
00:17:13.920 All right, the company is very happy!
00:17:20.640 Yes, there’s the question: are the tests using the fake die?
00:17:30.480 Yes, that’s right.
00:17:36.960 In the real world, I would actually suggest testing end-to-end, or at least not unique tests with fake die only.
00:17:42.120 But it’s not a real world; it’s a story.
00:17:50.280 That’s a good point, and we actually should include those in tests.
00:17:55.760 Only if we don’t want to test this with unit tests, you can go ahead and use a fake die.
00:18:01.680 Okay, we did it! Our company is happy—a very rich company now.
00:18:09.240 We’re also very rich because look at our resume.
00:18:15.840 There’s one more problem here—one last tiny thing.
00:18:22.560 Our code looks like it works perfectly, but we still get a call from this one customer.
00:18:30.120 He tells us that he played with his friend April 5 Heroes, won, and I still lose.
00:18:37.040 It shouldn’t supposed to work like that.
00:18:42.480 Yeah, it shouldn’t, and Fredo is a bit angry because the tests show that everything works.
00:18:47.520 Tests are green. It has to work.
00:18:53.880 So he was about to grab a phone and kindly explain to the customer why it works.
00:19:01.200 But on the other hand, I think he briefly remembers the project.
00:19:07.920 Maybe you also remember such projects where tests were green and yet features didn’t work.
00:19:14.520 Have you and anyone? Yeah, less than half that I hoped for.
00:19:20.520 All right, tests are green but can we actually prove that our code works?
00:19:29.760 Fredo talks with his group and has an idea.
00:19:35.880 Right now, when the game ends, we know who wins.
00:19:41.760 But it would be really nice if we could tell why that person won.
00:19:47.520 Because look at this: if player one wins, it means he could have rolled a six.
00:19:54.480 His opponent could have rolled a one, two, or three. They got it.
00:20:01.920 There are many events that lead to the same result.
00:20:09.120 It would be really nice if we could somehow track this.
00:20:15.360 So he gets an idea: it would be really nice if we had a game that actually returns some events.
00:20:22.560 Some logs, some audits. So let’s say our fake die rolls a two and a one.
00:20:30.720 We want to have an event that says that P1 rolled a two, maybe rolled a one.
00:20:36.480 And that the winner is P1.
00:20:43.260 Because then we would exactly know what happened and why P1 won.
00:20:49.560 Not only that, he won.
00:20:55.560 All right, so to do that, we add events here.
00:21:02.280 Let’s initialize it. This is important: after each one of the state changes.
00:21:09.960 Every time we use the instance variable or assign a new value to it, we want to log it.
00:21:18.840 So player one rolls something, player two rolls something, and finally who the winner is.
00:21:25.920 Right now, you can actually take a look at those events.
00:21:33.600 Maybe you can store them in a database, maybe you can log them somewhere else.
00:21:39.720 Like Sumo Logic or Datadog, or whatever you use, and you can actually follow the full execution of your code.
00:21:48.600 See what was happening and assert the code actually behaves as we expected in tests.
00:21:54.120 So one final thing: tests are still green! Everyone is clapping.
00:22:01.920 Fredo learned a new skill.
00:22:07.560 With such an impressive resume, he becomes a president. His journey ends here.
00:22:15.600 However, ours does not—not yet, at least.
00:22:21.000 I'd like to go through some of those tests with you and talk a bit about them.
00:22:26.760 Let’s start with the ones with conditionals.
00:22:33.600 Those are very obvious examples of how not to write tests.
00:22:39.480 We have logic in tests—that's the main problem.
00:22:46.920 What’s bad about it? To be fair, I don’t think there is anything good about them.
00:22:53.760 Logic in tests always makes them harder to understand.
00:23:01.320 Logic in tests that mimics the logic in code actually means that you’re probably not testing anything.
00:23:07.320 It gives you a false sense of security, so don’t use it.
00:23:15.600 Another question: who has ever seen logic in tests?
00:23:21.480 Hands up—no one? Okay.
00:23:27.780 So there are different flavors of logic.
00:23:34.320 Have you ever seen a loop in tests?
00:23:41.280 Yeah, that’s logic, because why is it bad?
00:23:47.480 Not every logic is bad, but when you have a loop like that, you test 100 products.
00:23:55.560 If the test fails, it returns 101 instead of one. For which product did it happen? It’s hard to tell.
00:24:03.240 It should be understandable immediately.
00:24:10.560 Have you ever seen something like that? I've seen that.
00:24:17.520 We have this nice serializer that turns cents to dollars.
00:24:24.960 Our code already uses it, so let's use it in our tests.
00:24:31.920 Well, if cents to dollars breaks and starts returning nil, our code will still pass.
00:24:38.400 But that means our feature won’t work.
00:24:44.960 Okay, the second thing is the one with stubbing.
00:24:52.560 Now we’re getting to the more controversial aspects.
00:24:59.760 Why it’s good and why it’s bad. The good thing is that we’re actually testing things.
00:25:06.480 And we’re testing all of them. Another good thing is that those tests are deterministic.
00:25:13.920 No matter how many times we run them, we expect the same thing to happen, which is good.
00:25:20.520 They are easy to write, so let’s acknowledge that.
00:25:26.640 What’s bad about them? They make your code coupled to implementation.
00:25:34.600 This can complicate refactoring, as we’ve seen in this example.
00:25:41.040 Okay, so hands up: who uses stubs or mocks in code?
00:25:48.720 Yeah! Have you ever seen something like that?
00:25:55.680 Like where you’ve changed the variable name, but the amount of those attribute values is accurate?
00:26:03.480 Good luck if you want to refactor it anytime soon.
00:26:09.720 Also, you know, results is a double, and it allows results to return something else.
00:26:15.480 This returns another double. It’s hard to understand.
00:26:22.320 And tests are supposed to be easy.
00:26:29.040 Client or any other action.
00:26:34.320 If you have documentation for the external API, injecting it into your class.
00:26:43.200 You will have the fake dice available. This kind of expects to receive that role would be useful.
00:26:48.840 This is the only thing that is called a different right way.
00:26:56.160 I fully agree it can be useful.
00:27:02.880 It just comes with a price, and as long as you’re aware of that, you’re good to go.
00:27:09.840 I’m not telling you to avoid using any of those things.
00:27:15.120 Just honestly, it comes with a price.
00:27:21.600 There are functions or methods that we don’t really care about what they return, only about side effects, like an API call.
00:27:30.960 We have to test it somehow, and I think this is a good way to do that.
00:27:39.120 Perhaps there are more benefits than the hassle of refactoring later.
00:27:46.760 Maybe we won’t refactor this—which is even better.
00:27:51.720 So yeah, if it works for you, work with it.
00:27:57.600 But if you start using stubs everywhere, ask yourself if it’s worth it.
00:28:05.760 If you see receive message chains, this should light up some heavy orange lights in your head.
00:28:13.680 Okay, let’s go to dependency injection.
00:28:19.680 Anyone uses something similar in tests?
00:28:27.120 All right, how does it work for you? Is it fun? Is it easy to implement?
00:28:34.320 You use a different class specifically for tests?
00:28:41.760 Miller is actually maybe talking about this tomorrow, and it’s called Substitute.
00:28:47.520 I don't know if you've arrived from there as well. I have problems convincing others to accept non-production code.
00:28:55.080 They seem to always say: hey, it’s not production code.
00:29:02.520 So what’s your reaction to testing? This is the product.
00:29:08.760 Yeah, I can feel that it’s hard.
00:29:14.840 If you instead of making a new class you use an instance double, then it suddenly becomes really nice.
00:29:21.600 Okay, let’s talk about what’s good in my opinion about injecting tests.
00:29:29.520 Like independence injection tests lets the code be open, which is actually a big thing.
00:29:37.680 When your code changes a lot, those tests are still deterministic.
00:29:44.640 We gain some decoupling from implementation, which is actually very good because it makes refactoring much easier.
00:29:51.360 What’s bad about it? Well, first of all, as you mentioned, some people don’t want to do it.
00:29:59.760 But fake die needs to be added like it’s a code.
00:30:08.160 I mentioned that when we add code or logic to tests, it makes them less readable.
00:30:14.520 The second thing is we need to make sure that fake dice and dice stay aligned.
00:30:21.180 If methods on a die change, we should change them on fake dice.
00:30:27.300 It’s tricky.
00:30:34.020 Lastly, if we pick the wrong abstraction, there’s a big chance that we will regret it.
00:30:40.920 It will make the code more complicated than it needs to be.
00:30:47.520 There’s one thing here I want to point out because I can see a lot of instance double uses.
00:30:54.240 It guards us from using methods that don’t exist.
00:31:01.440 But it doesn’t help us in returning values that are impossible.
00:31:08.520 For instance, if our calculate method returns an integer and in our instance double we return a string.
00:31:15.720 If we do something like that in our tests, our tests will test something different than our code.
00:31:22.980 So keep this in mind.
00:31:29.520 All right, so what about the tests with monitoring?
00:31:35.760 What about logging, like whatever you call it—auditing?
00:31:41.640 It’s actually a very good idea. I highly recommend it, especially in important parts of your system.
00:31:48.180 It makes debugging a lot easier.
00:31:55.200 It gives you an audit of changes.
00:32:02.520 At the very last thing, it gives you the ability to manually test it.
00:32:08.520 If you have a complicated algorithm and you know all the inputs, you can use your calculator on your phone.
00:32:15.840 You can test if the value is matching the one that was calculated from your code.
00:32:23.640 Of course, if you use the technique that was already mentioned yesterday and a few times today called event sourcing.
00:32:31.320 You get this for free because you already have those events that alter the state of an object.
00:32:39.720 What’s tricky about logging is if you overuse it in your domain code.
00:32:47.760 Or in the code that cares about business logic, it becomes hard to read because you log everything.
00:32:54.720 Do something, log, do something, log, do something, log.
00:33:02.520 The second thing is if you don’t properly choose the tools, you might end up with a pricey bill.
00:33:09.600 If you log extensively under heavy traffic, your Sumo Logic bill might increase.
00:33:15.840 Think about it; maybe it’s better to store them in a database. Maybe a simple Datadog matrix would be sufficient.
00:33:24.180 Pick the right tools for the job. I also recommend using this with legacy code.
00:33:30.600 It actually helped me a few times with understanding and debugging the code.
00:33:37.680 When you have a big ball of mud and you add logging to the mix, you will still have a big pile of mud.
00:33:45.600 But you might understand it a tiny bit better.
00:33:52.680 So I recommend you to try it. Okay.
00:33:58.560 Now, back to the original question: how to test randomness?
00:34:02.400 In my opinion, don’t test randomness. Try to understand it.
00:34:08.520 Try to extract it, and at the very end, try to control it.
00:34:12.720 Yeah, you might think there is no randomness in your systems.
00:34:19.680 And you might be right because why wouldn’t it be?
00:34:25.200 But there’s one thing that looks very similar to random things.
00:34:31.800 Maybe some of you have seen a piece of code like that somewhere in the system, like time current.
00:34:38.520 I bet if we all right now run race console on our MacBooks, we would all get different results.
00:34:46.440 It kind of looks like it’s a random thing.
00:34:53.520 Although, let’s be real here: it’s not that complex.
00:34:58.560 This code looks pretty simple, so here is my favorite solution.
00:35:05.160 How should we test it? Time travel!
00:35:09.120 Yeah, that’s the only option to test this fair and straightforward piece of code.
00:35:15.840 We need to use time traveling.
00:35:21.720 Okay, that’s it from my side.
00:35:27.720 But I have one more question or maybe one more favor to ask you.
00:35:33.480 This QR code leads to a feedback form.
00:35:40.320 There’s a slight chance that I might give this talk sometime in the future.
00:35:46.680 So I would really appreciate it if you could give me feedback. It’s really quick.
00:35:54.720 You just open the form, type in, "I hated it" because this is the important stuff for me.
00:36:00.600 Okay, thanks. That’s all from my side.
00:36:07.080 If you have any questions, I will be happy to answer.
00:36:18.480 I just want to challenge your statement: the last statement that time travel is the only test.
00:36:24.600 To test the time current or time now, I know at least two other battles.
00:36:30.240 One is effects like algebraic effects, and the other is dependency injection.
00:36:37.680 You can have like a single current time initialized per request or per whatever process you have and inject it down to the system.
00:36:44.520 Yeah, I mean, I 100% agree with you. This is probably much better.
00:36:51.600 You can use stubs or whatever, like probably even some logic I show here.
00:36:57.720 I agree, and yet I still sometimes see a piece of code like that in our system.
00:37:05.880 So, I agree you’re right; you can test it in many better ways.
00:37:12.480 So yeah.
00:37:18.000 Any more questions? All right, thank you very much.
00:37:30.840 Okay, so...