Showing posts with label Unit Testing. Show all posts
Showing posts with label Unit Testing. Show all posts

Saturday, September 7, 2019

Test Driven Deck

While having a plan for testing your code is important, Test Driven Development (TDD) takes this to another level. The idea here is that you write automated tests before you start writing the code. When it is practical to do this, it is an incredibly good way of creating code. Planning tests gets you thinking about the code you are going to write – hopefully with an idea of the fringe cases that you are going to encounter. Writing the tests give you something to check the code against. All tests should initially fail, with a successful test likely indicating either an error with the test or an error with the test plan.

You then write the code and run it against the tests trying to pass one test at a time. Once you have passed all the tests and no missing tests have been discovered, you are finished the code and can start planning the tests for the next piece of code that you need to write. Having automated tests also means that it is easy to have the tests running frequently while you do other things and if something breaks then you know right away and as it is likely what you (or someone on your team) is currently working on, it will be trivial to fix the bug! Remember that in general the quicker you can find a bug, the less it will cost to fix it. This cost is in time, but can also be in money if the bug is in a production version and you have marketing and patching costs in addition to the cost of finding and fixing a bug.

We have a card class that can display any card, so what we need next is a deck of cards. This deck needs to be able to be shuffled and we need to be able to deal cards from the deck. So, how would we test such a beast?

In a sorted deck, the cards should be from 1 to 52 so simply drawing cards from a sorted deck and making sure they are in sequence would solve this problem. A shuffled deck, however, has two issues that we need to check for. First, we want to make sure that all the cards are in the shuffle (that we haven’t duplicated cards losing some cards or other similar problem). Next we want tom make sure the cards are not in order. Simply checking to see the card is different from its position in the deck will not work as we would expect that at least some of the time a randomly shuffled card would end up in the proper deck position. A good shuffle would have at least half the cards in a different position so simply counting how many cards don’t match would suffice most of the time.

As the deck class can be written without the card class, as it uses card IDs and not instances of cards, it is possible to write the deck class in its own html file which I called deckTest. This starts off with your typical html5 boilerplate followed by a simple version of the Deck class with none of the necessary methods implemented.



Deck JavaScript Test


test results go here





Now some of you may have noticed that there is a lot of test code here. This is the downside to test driven development. You will often end up with test code that is the same size as the code that you are testing, and sometimes even larger. The plus side is that you know your code works within the testing parameters and if you refactor or change code you will be able to check to make sure that nothing you have done is broken. Manual testing could have been done with a lot less code. As always there is a trade-off that must be made. In a solo environment, and possibly a small team, manual testing may be adequate and may be productive enough. As you start to get to larger teams, people inadvertently mucking up other people’s code happens a lot more often than you would expect.

Sunday, September 26, 2010

A Break for Bugs

I am going to delay the planned installment of Animating the Canvas this week. While I have made a lot of progress on the code and thought that I had the rest of this series finished, when using the code within my Tarot project, some bugs were uncovered. While I could continue the series anyway, as the planned topic for today would not have been related to the issue at hand, I have decided instead to take a brief break and discus testing.

Testing and debugging are an important part of programming. The testing requirements largely depend on the project. Being old-school, I tend to use my brain to do the bulk of my debugging. I try and think like the computer to figure out where the problem is and then isolate and solve the problem. I find this approach much faster than the second level of debugging, namely using a debugger. Firefox, thankfully, has an incredible debugger called firebug. Apple has pretty much cloned this tool for Safari. Still, as someone who uses multiple operating systems, I like the fact that Firefox is everywhere so tend to use that browser for my preliminary testing. Single stepping through a program can be very time-consuming but for some bugs it is a necessity.

The big trend now is something called unit testing. It is an approach that is really good and is something that I should be doing more of but as most my projects are small I don't. The idea here is that you write your tests before you write your code. The tests are usually written using some type of testing framework in mind. Because the tests are all automated, you simply need to run the tests before checking in code. The advantage to using this technique is that you know when you are done as all of your tests are successful. For game development, this is only a partial solution. You can test the subsystems that make up the game, but are still going to need human testing for a lot of the testing.

While unit testing is not the silver bullet a lot of people think, the automated tests do help you make progress if you have written them. If you have not and are debugging things, unit tests can still prove useful. Once you have isolated a bug, or started writing testing code to help find the bug, you will have automated tests that make sure you do not re-introduce the bug in the future. While I am sure there are countless JavaScript testing frameworks available, creating one is very simple. Here is the one I wrote after discovering my issues with the BGLayers library I am writing:

function addTestResult(group, desc, result)
{
    var testTable = document.getElementById('testTable');
    var rRow = testTable.insertRow(1);
    var resText;
    if ( result)
        resText = 'Test Passed';
    else
        resText = 'Test Failed';
    rRow.innerHTML = ''+group+''+desc+''+resText+'';
}

Yes, I could have searched out a much better one online, but was simply too lazy to. My own "framework" only took a few minutes to write. I am sure that as I continue to focus more on writing JavaScript, especially as I start larger projects,  finding a better library for unit testing will make sense. For now, my simple test function is adequate for my needs.