{"id":173,"date":"2011-01-13T08:00:00","date_gmt":"2011-01-13T08:00:00","guid":{"rendered":"https:\/\/pagan-gerbil.net\/?p=173"},"modified":"2011-01-13T08:00:00","modified_gmt":"2011-01-13T08:00:00","slug":"learning-unit-testing-vii-running-and-redesigning","status":"publish","type":"post","link":"https:\/\/www.pagan-gerbil.net\/?p=173","title":{"rendered":"Learning Unit Testing VII &#8211; Running and Redesigning"},"content":{"rendered":"<p>I can see this page 10 being a pretty big thorn in my side. After stating fairly clearly<\/p>\n<blockquote>\n<p>models can move up to their move rate<\/p>\n<\/blockquote>\n<p>under the \u2018Moving\u2019 heading, it then says<\/p>\n<blockquote>\n<p>A running fighter can move at double speed: 8&#8243; rather than 4&#8243;, for example.<\/p>\n<\/blockquote>\n<p>This is going to have a fairly large impact on the tests involved. The test for exceeding total movement (both in one and two moves) will only throw an exception if the total movement is double the model\u2019s Movement rate now. In addition, a new test is going to have to be added to ensure that moving over the Movement rate sets an &#8216;IsRunning\u2019 flag to true. The first test to add would be one that allows a model to move more than it\u2019s Movement rate, but sets the IsRunning flag.<\/p>\n<pre class=\"code\">[<span style=\"color: #2b91af\">TestMethod<\/span>]\n<span style=\"color: blue\">public void <\/span>MoveModel_MovesDistanceOverMovementRateAndSetsIsRunningFlag()\n{\n<span style=\"color: #2b91af\">Model <\/span>testModel = <span style=\"color: blue\">new <\/span><span style=\"color: #2b91af\">Model<\/span>();\ntestModel.Movement = 4;\ntestModel.PositionX = 0;\ntestModel.PositionY = 0;\ntestModel.PositionZ = 0;\n<span style=\"color: blue\">float <\/span>newX = 5;\n<span style=\"color: blue\">float <\/span>newY = 4;\n<span style=\"color: blue\">float <\/span>newZ = 3;\ntestModel.MoveModel(newX, newY, newZ);\n<span style=\"color: #2b91af\">Assert<\/span>.IsTrue(testModel.IsRunning);\n}<\/pre>\n<p>Even with the correct code added to MoveModel &#8211;<\/p>\n<pre class=\"code\"><span style=\"color: blue\">if <\/span>(<span style=\"color: blue\">this<\/span>.TotalDistanceMoved &gt; <span style=\"color: blue\">this<\/span>.Movement)\n{\n<span style=\"color: blue\">this<\/span>.IsRunning = <span style=\"color: blue\">true<\/span>;\n}<\/pre>\n<p>&#8211; this doesn\u2019t work. Because ValidateMove is throwing an exception (as we designed in earlier). So ValidateMove has to allow up to twice the MovementRate.<\/p>\n<pre class=\"code\"><span style=\"color: blue\">if <\/span>(GetDistanceFrom(positionX, positionY, positionZ) + <span style=\"color: blue\">this<\/span>.TotalDistanceMoved &gt; <span style=\"color: blue\">this<\/span>.Movement * 2)\n{\n<span style=\"color: blue\">throw new <\/span><span style=\"color: #2b91af\">ArgumentException<\/span>(<span style=\"color: #a31515\">\"The model cannot move further than it's Movement rate.\"<\/span>);\n}<\/pre>\n<p>Now, all the tests pass. But should they be? Checking my working, the MoveModel_CannotMoveFurtherThanModelsMovement test is moving the model more than twice it\u2019s movement rate. So it is correct to throw an exception, and therefore pass the test. Anything testing to stay beneath the model\u2019s Movement rate is obviously going to be beneath it\u2019s doubled Movement rate, so they will continue to pass. MoveModel_TotalMovementInASingleTurn&#8230; that tests whether two movements that combined make more than the model\u2019s Movement is also working correctly. But I\u2019ve noticed I had an error in that test:<\/p>\n<pre class=\"code\">[<span style=\"color: #2b91af\">TestMethod<\/span>]\n<span style=\"color: blue\">public void <\/span>MoveModel_TotalMovementInASingleTurnCannotExceedModelMovement_ThrowsArgumentException()\n{\n<span style=\"color: blue\">bool <\/span>correctExceptionThrown = <span style=\"color: blue\">false<\/span>;\n<span style=\"color: blue\">try\n<\/span>{\n<span style=\"color: #2b91af\">Model <\/span>testModel = <span style=\"color: blue\">new <\/span><span style=\"color: #2b91af\">Model<\/span>();\ntestModel.Movement = 4;\ntestModel.PositionX = 0;\ntestModel.PositionY = 0;\ntestModel.PositionZ = 0;\n<span style=\"color: blue\">float <\/span>newX = 5;\n<span style=\"color: blue\">float <\/span>newY = 4;\n<span style=\"color: blue\">float <\/span>newZ = 3;\ntestModel.MoveModel(newX, newY, newZ);\ntestModel.MoveModel(0, 0, 0);\n}\n<span style=\"color: blue\">catch <\/span>(<span style=\"color: #2b91af\">ArgumentException <\/span>ex)\n{\ncorrectExceptionThrown = <span style=\"color: blue\">true<\/span>;\n}\n<span style=\"color: #2b91af\">Assert<\/span>.IsTrue(correctExceptionThrown);\n}<\/pre>\n<p>The try catch was working on both MoveModel calls \u2013 and those values (after the calculation fix a couple of posts back) would have sent it way over the Movement on the first move, not the second. Moving the try&#8230;catch so that it only covers the second call to MoveModel would check that it\u2019s failing in precisely the right place. By reversing my change to ValidateMove, I can confirm that the test would have failed before if the try&#8230;catch was in the right place. Putting it back in, and it throws an exception on the second MoveModel call, just as it should do. All the tests pass, and I\u2019m a little more comfortable about them testing the right thing.<\/p>\n<p>Lesson learned: Only test exactly the line you expect to break things.<\/p>\n<p>The rest of the \u2018Running\u2019 section mentions not being able to shoot \u2013 this is something that we can cover in the Shooting section (after Movement), and isn\u2019t important right now. The next bit that should matter is that a running model must stop 8 units away from an enemy model that he can see. This brings a number of things into play immediately:<\/p>\n<ol>\n<li>Can we identify models as being enemies?\n<li>Can we identify which models can see others?\n<li>How do we perform the sight checks all along it\u2019s movement to work out if it can see the enemy (they may not be in sight at the beginning of the move, only halfway along it)?\n<li>What action should be taken if the model\u2019s movement is disrupted \u2013 should it still count as running? How can it be prevented from moving further? <\/li>\n<\/ol>\n<p>Before we write tests, we should explore the problem a bit further.<\/p>\n<p>Essentially, the enemy is at the centre of a circle 16 units in diameter (radius of 8). The active model\u2019s path may intersect the circle at some point. If it does so, the active model must stop at the point along that path nearest to his starting point, providing that he can draw a line of sight to the enemy model at the centre of the circle.<\/p>\n<p>So we only really need to work out if any point of the active model\u2019s path intersects the enemy \u2018disruption\u2019 circles, and check those sections of the path for line-of-sight to the centre of the circle.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I can see this page 10 being a pretty big thorn in my side. After stating fairly clearly models can move up to their move rate under the \u2018Moving\u2019 heading, it then says A running fighter can move at double speed: 8&#8243; rather than 4&#8243;, for example. This is going to have a fairly large &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.pagan-gerbil.net\/?p=173\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Learning Unit Testing VII &#8211; Running and Redesigning&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[14],"tags":[43,62,63,64],"series":[73],"_links":{"self":[{"href":"https:\/\/www.pagan-gerbil.net\/index.php?rest_route=\/wp\/v2\/posts\/173"}],"collection":[{"href":"https:\/\/www.pagan-gerbil.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pagan-gerbil.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pagan-gerbil.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pagan-gerbil.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=173"}],"version-history":[{"count":0,"href":"https:\/\/www.pagan-gerbil.net\/index.php?rest_route=\/wp\/v2\/posts\/173\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.pagan-gerbil.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=173"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pagan-gerbil.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=173"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pagan-gerbil.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=173"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/www.pagan-gerbil.net\/index.php?rest_route=%2Fwp%2Fv2%2Fseries&post=173"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}