In this video, I'll show you how I would reorganize the random square function to be more testable.
So the problem with computerFire and 0:00 computerPlaceShip is that they have random outcomes built in. 0:02 Each of these functions really does two different things. 0:07 First they build a random location, then they do something with that location, 0:10 like fire a shot or place a ship. 0:15 In programming, we call this tight coupling when two distinct functions 0:19 are bundled up so that they can only really be used together. 0:23 Now a hallmark of tightly coupled code is that it makes our job of writing unit 0:26 tests harder. 0:30 So to refactor this code I think we can actually just 0:32 abstract those two ideas apart. 0:34 We see that the same code appears in both the computerFire and 0:37 computerPlaceShip functions, 0:41 the part that generates two numbers in the board range and puts them in an array. 0:43 So we can pull that out into its own function that returns the result. 0:47 Let's call the function getRandomCoordinates. 0:51 Then I'll cut the variable declarations for x, y, and coordinates out of 1:06 the computerFire function and paste them inside getRandomCoordinates. 1:10 So now to put the x and y numbers in an array, 1:16 instead of var coordinates = x, y, we'll say return x, y. 1:19 So now I can delete these from computerPlaceShip as well. 1:26 So, computerPlayShip also randomly chooses horizontal or vertical. 1:34 So we can use the same strategy by pulling out that logic into a separate function. 1:40 Let's call this function getRandomDirection. 1:46 So now I'll go ahead and cut the direction declaration out of 1:56 computerPlaceShip and paste it inside getRandomDirection. 2:01 And in this function instead of var direction equals = 2:07 Math.random, we'll say return Math.random. 2:12 So at this point there's actually nothing left of our original 2:18 functions besides a call to fire and placeShip. 2:22 So, at the bottom of our file we can remove the module that exports for 2:26 computerPlaceShip and computerFire. 2:30 But now we can also use the randomizers with the existing fire and 2:35 placeShip functions in place of the original computer functions. 2:39 So for example, we can set up the game to call fire and 2:51 placeShip with some attempted random coordinates in-between human player turns. 2:55 Like this. 3:01 We also get to use these randomizer functions in other parts of our game 3:15 engine if we need to. 3:18 That's a big plus. 3:20 More reusable code will save us time later. 3:21 And this way we don't have to add any tests at all. 3:26 In fact, this is another thing that writing tests helps us with. 3:29 When it's hard to write tests for something, 3:33 you might wonder whether you really need that function in the first place. 3:36 And this way, writing tests can guide us toward simpler code. 3:40 We still can't do a super meaningful test for 3:43 the randomizer functions because of their random nature. 3:46 But we've pulled the random pieces apart from our other application code so 3:49 that our other parts remain testable. 3:54 Thinking about good unit test has improved our code yet again, 3:56 making it more reusable and modular. 4:00 We've learned a lot in this stage. 4:15 Set up and tear down in our test suites, testing for 4:17 edge cases, and keeping our code decoupled and testable. 4:20 So you're ready to use Mocha and Chai to keep doing BDD in your applications. 4:23 In the last stage, I'll show you some other convenient ways to display your test 4:29 results and introduce some more advanced features of Mocha. 4:32
You need to sign up for Treehouse in order to download course files.Sign up