1 00:00:00,170 --> 00:00:04,360 The fire function is one of the last things the game engine actually needs. 2 00:00:04,360 --> 00:00:08,430 Isn't it amazing how fast we can build stuff that sounded hard before we started? 3 00:00:08,430 --> 00:00:11,620 So here's how I wrote my test suite for the fire function. 4 00:00:11,620 --> 00:00:12,603 All right. So first, 5 00:00:12,603 --> 00:00:17,157 I'll set up my test suite at the bottom of the shiptest.js file. 6 00:00:20,687 --> 00:00:27,800 The test suite is named fire, so I'll pass fire as the string followed by a function. 7 00:00:35,526 --> 00:00:38,670 Then I’ll import the fire function at the top. 8 00:00:38,670 --> 00:00:40,600 So it's available to all my specs. 9 00:00:56,685 --> 00:01:00,645 I'll skip running the initial test in this case because i know it's just going to 10 00:01:00,645 --> 00:01:04,080 break at first, but it's a good habit for you to keep. 11 00:01:04,080 --> 00:01:07,840 All right, so now I need a spec to test fire's behavior. 12 00:01:07,840 --> 00:01:11,170 The first thing that comes to mind for this function is that it should record 13 00:01:11,170 --> 00:01:13,870 damage on the correct ship, if there's a hit. 14 00:01:13,870 --> 00:01:18,677 So I'll create a new spec that says, it should record damage. 15 00:01:20,942 --> 00:01:22,521 On the given player ship. 16 00:01:27,636 --> 00:01:29,290 At a given coordinate. 17 00:01:40,585 --> 00:01:43,749 So now, I need to tell fire which player I'm targeting and 18 00:01:43,749 --> 00:01:46,010 which location i'm guessing. 19 00:01:46,010 --> 00:01:50,410 So, it should accept a player parameter and a coordinate parameter. 20 00:01:50,410 --> 00:01:53,510 That means I need a player object for this test. 21 00:01:53,510 --> 00:01:55,053 So, I'll say var player. 22 00:02:00,608 --> 00:02:05,067 And the player will need at least one ship at one location. 23 00:02:08,699 --> 00:02:13,614 So, I'll say locations. 24 00:02:13,614 --> 00:02:17,230 0, 0. 25 00:02:17,230 --> 00:02:20,025 And after the location, I'll add a damage array. 26 00:02:26,708 --> 00:02:32,194 So if I set up a simple player object and call fire at a location 27 00:02:32,194 --> 00:02:37,373 I know is occupied, so let's say fire player at 0,0. 28 00:02:40,748 --> 00:02:45,870 The players only ship should have a matching coordinate and its damage record. 29 00:02:45,870 --> 00:02:49,100 Basically the ship should take damage at the given location. 30 00:02:49,100 --> 00:02:51,440 So let's write an expectation for that. 31 00:02:51,440 --> 00:02:55,661 So right below will say, 32 00:02:55,661 --> 00:03:02,698 expect (player.ships[0].damage 33 00:03:02,698 --> 00:03:08,130 [0]).to.deep.equal. 34 00:03:12,780 --> 00:03:18,570 And then will add 00. 35 00:03:18,570 --> 00:03:27,030 So, if we run the test now in the console, we can see that the test breaks at first. 36 00:03:31,615 --> 00:03:36,575 So now let's go ahead and set up the fire function in ship_methods.js. 37 00:03:36,575 --> 00:03:42,486 So right below the damageShip function, I'll create a new function called fire. 38 00:03:47,139 --> 00:03:52,299 And we'll pass the fire function two parameters, 39 00:03:52,299 --> 00:03:55,800 player and coordinates. 40 00:03:55,800 --> 00:04:00,668 Then I'll go ahead and export the fire function at the bottom 41 00:04:00,668 --> 00:04:05,067 of our file by saying module.exports.fire = fire. 42 00:04:10,280 --> 00:04:15,220 So now if I go over to the console and run npm test. 43 00:04:17,470 --> 00:04:20,440 We can see that the test gives me an assertion error. 44 00:04:20,440 --> 00:04:25,366 It says, expected undefined to deeply equal [ 0, 0 ]. 45 00:04:25,366 --> 00:04:30,470 Now, the fire function doesn't yet do anything to the target ship. 46 00:04:30,470 --> 00:04:34,350 But I know that in the end if a ship exist on my opponent's board 47 00:04:34,350 --> 00:04:39,430 at the location I guessed I want to run damageShip on that particular ship 48 00:04:39,430 --> 00:04:42,270 using the location I guessed when calling fire. 49 00:04:46,840 --> 00:04:50,290 So I'll start with check for ship using my guess and 50 00:04:50,290 --> 00:04:54,710 the given player since this returns a true or false value. 51 00:04:56,200 --> 00:05:02,120 So inside my function I'll save it to a variable named ship to use it internally. 52 00:05:03,500 --> 00:05:09,560 Then I'll pass player and coordinates as the arguments. 53 00:05:09,560 --> 00:05:13,660 So, I don't need to worry at all whether check for ship will work here. 54 00:05:13,660 --> 00:05:18,060 Because my test suite has already proven that it does exactly what I expect. 55 00:05:18,060 --> 00:05:19,550 And that's super awesome. 56 00:05:19,550 --> 00:05:21,850 It takes a huge load off my brain. 57 00:05:21,850 --> 00:05:25,530 It's kind of like knowing that a j.query function will just work and 58 00:05:25,530 --> 00:05:27,440 you don't need to second guess it. 59 00:05:27,440 --> 00:05:31,090 So here, I'm calling the variable ship, because that's what it represents. 60 00:05:32,100 --> 00:05:37,870 Okay, so if my opponent has a ship where it guessed, then I wanted to take damage, 61 00:05:37,870 --> 00:05:43,890 so I know which coordinates to pass in, but how do I know which ship to pass? 62 00:05:43,890 --> 00:05:48,130 Now, I could run through all my opponents' ships and look for the one I want. 63 00:05:48,130 --> 00:05:51,160 But that's already what checkForShip does. 64 00:05:51,160 --> 00:05:53,520 And I don't want to repeat all that logic here. 65 00:05:53,520 --> 00:05:57,900 So instead, let's just go refactor the checkForShip method. 66 00:05:57,900 --> 00:06:00,525 Remember when I warned you that we might have to adjust our for 67 00:06:00,525 --> 00:06:02,035 functions, as we go. 68 00:06:02,035 --> 00:06:05,075 So it's okay to throw away code that was working, 69 00:06:05,075 --> 00:06:08,075 even if we spent time writing tests for it already. 70 00:06:08,075 --> 00:06:12,175 In fact, this is one of the biggest benefits of having unit test, red, 71 00:06:12,175 --> 00:06:13,957 green, refactor. 72 00:06:13,957 --> 00:06:18,637 Even though our test for checkForShip are passing, it turns out we need check for 73 00:06:18,637 --> 00:06:20,927 ship to work slightly different now. 74 00:06:20,927 --> 00:06:27,017 So, our unit tests will tell us exactly what breaks and how as we rebuild things. 75 00:06:27,017 --> 00:06:28,777 So this is an easy fix. 76 00:06:28,777 --> 00:06:33,180 I'll just have the checkForShip function return the actual ship. 77 00:06:33,180 --> 00:06:36,820 And instead of simply returning true when finding a ship. 78 00:06:36,820 --> 00:06:38,970 So replace true with ship. 79 00:06:40,320 --> 00:06:44,760 And I've checked for ship find something then I wanna call damaged ship 80 00:06:44,760 --> 00:06:46,990 on that ship at my guessed location. 81 00:06:46,990 --> 00:06:50,546 So in my file function I'll say. 82 00:06:50,546 --> 00:06:56,809 If ship, then damageShip and 83 00:06:56,809 --> 00:07:04,910 pass the ship and the coordinates. 84 00:07:04,910 --> 00:07:07,750 All right, so let's see what the test reports. 85 00:07:07,750 --> 00:07:11,581 In my console, I'll run npm test. 86 00:07:13,370 --> 00:07:18,090 Well, this is interesting, it looks like all my checkForShip tests are now 87 00:07:18,090 --> 00:07:23,180 failing because I've dramatically changed the way checkForShip works. 88 00:07:23,180 --> 00:07:26,749 But it looks like my fire test passes, so that's good. 89 00:07:32,346 --> 00:07:39,160 So back inside ship_test.js scrolling all the way up to my checkForShip suite. 90 00:07:39,160 --> 00:07:41,430 I can quickly fix my test up. 91 00:07:41,430 --> 00:07:43,690 Now, my first test Is fine. 92 00:07:43,690 --> 00:07:47,670 Because it still returns false when it's finding nothing. 93 00:07:47,670 --> 00:07:54,902 But i'll change my next specs expectation to.deep.equal. 94 00:07:58,749 --> 00:08:05,417 Then I'll pass (player.ships[0]). 95 00:08:05,417 --> 00:08:09,046 All right, let's go over to the console and run the test again. 96 00:08:16,198 --> 00:08:20,343 And I see that my test is green now for that particular spec, so 97 00:08:20,343 --> 00:08:23,400 great now I know this strategy works. 98 00:08:23,400 --> 00:08:28,460 Now moving forward for all tests to pass we'll need to make similar 99 00:08:28,460 --> 00:08:32,160 deeper quality comparisons in the checkForShips suite, so 100 00:08:32,160 --> 00:08:37,490 we'll edit some of our other expectations to expect an array instead of troop. 101 00:08:37,490 --> 00:08:40,720 Now we can simply copy and paste this deep.equal 102 00:08:40,720 --> 00:08:44,460 expectation across the rest of the checkForShip suite, change some of 103 00:08:44,460 --> 00:08:48,660 the values to match the first member of an array, and everything should work great. 104 00:08:54,880 --> 00:09:00,320 All right so I'll copy this deep.equal method, from this expectation. 105 00:09:00,320 --> 00:09:02,890 Then scroll down to the next spec. 106 00:09:04,160 --> 00:09:07,877 Then replace the first and second expectation. 107 00:09:11,676 --> 00:09:13,640 Will leave the values at 0. 108 00:09:13,640 --> 00:09:20,470 Then scroll down to the next spec and replace all of these as well. 109 00:09:20,470 --> 00:09:26,980 So we'll change the first one from to be true to deep.equalplayer.ships at 0. 110 00:09:26,980 --> 00:09:29,420 We'll do the same for the next one. 111 00:09:31,910 --> 00:09:36,690 And this one will change the value to one and 112 00:09:36,690 --> 00:09:40,250 will do the same for the next one change that so one, and 113 00:09:40,250 --> 00:09:44,900 finally we'll replace the fifth one and change this value to two. 114 00:09:48,210 --> 00:09:51,220 Finally, I'll scroll down to my fire suite. 115 00:09:51,220 --> 00:09:54,930 Then I'll create one more spec here inside the fire suite 116 00:09:54,930 --> 00:09:59,060 by copying the first spec and pasting a new spec right below. 117 00:10:01,570 --> 00:10:06,161 I'll change this new spec's description to should not 118 00:10:06,161 --> 00:10:10,466 record damage if there is no ship at my coordinates. 119 00:10:16,888 --> 00:10:21,394 So when I change the target here to [9, 9], 120 00:10:21,394 --> 00:10:26,170 I would expect the damage array to be empty. 121 00:10:26,170 --> 00:10:32,330 So let's change the expectation to say, to.be.empty. 122 00:10:32,330 --> 00:10:37,340 Then remove the second 0 value here after damage, so let's see, 123 00:10:37,340 --> 00:10:41,790 does fire now correctly leave the ship on damage if we guess wrong? 124 00:10:41,790 --> 00:10:43,600 Well let's see. 125 00:10:43,600 --> 00:10:47,060 I'll go over to the console and run npn test. 126 00:10:50,690 --> 00:10:52,443 And yep, the test already passed. 127 00:10:55,038 --> 00:10:59,254 Now, I might also want to add some reporting to the fire function so 128 00:10:59,254 --> 00:11:02,650 that players know whether they hit or not. 129 00:11:02,650 --> 00:11:04,180 Since this is just a game engine, 130 00:11:04,180 --> 00:11:07,290 we'd probably have a separate reporting function 131 00:11:07,290 --> 00:11:11,659 that did fancy stuff with the DOM or printed a useful message in the console. 132 00:11:12,980 --> 00:11:14,700 For now, this looks really good. 133 00:11:14,700 --> 00:11:17,810 We have almost all the major logic for the game in place. 134 00:11:17,810 --> 00:11:19,780 Did you use other assertions in your tests? 135 00:11:19,780 --> 00:11:22,110 Did you build your fire function differently? 136 00:11:22,110 --> 00:11:25,350 Share your solutions in the community and compare them to what you see here. 137 00:11:26,490 --> 00:11:29,480 In this stage, we've learned how to set up our files from Mocha. 138 00:11:29,480 --> 00:11:32,380 The main file structure of a test suite in Mocha and 139 00:11:32,380 --> 00:11:36,270 a lot of useful chai assertions to make writing test easy. 140 00:11:36,270 --> 00:11:42,140 We also did a lot of BDD to outline the basic logic of a battleship game engine. 141 00:11:42,140 --> 00:11:44,920 It can feel strange, but with practice you'll find that it 142 00:11:44,920 --> 00:11:48,390 really is super helpful to outline your ideas first. 143 00:11:48,390 --> 00:11:51,360 We were able to refactor things easily and 144 00:11:51,360 --> 00:11:54,170 know exactly what changed in our code base. 145 00:11:54,170 --> 00:11:56,780 Manual testing can never give us that level of confidence. 146 00:11:58,010 --> 00:12:01,800 And the next stage we'll learn some great features of Mocha for reducing the amount 147 00:12:01,800 --> 00:12:05,560 of test code we write, while also improving the quality of our test output.