Learning Progress

First post in March… how is it already March!?

I noticed that I tend to drift between the aspects of my learning, devoting most of my attention to one branch at a time. Sometimes I blog a lot, sometimes I code a lot, and other times I “hit the books” a lot. Usually the increased focus on one branch leads to less time spent on the others. I am trying to find a good balance, because all three of those activities help me learn.

I enjoy talking about programming and about learning programming. The social aspects keep me motivated. Exchanging stories and ideas with others who are at various stages of learning to program helps me through the rough patches. Also, getting my ideas out, “on paper,” or in a screencast or video, helps me understand those topics better. Figuring out how to explain something forces me to look at it from another perspective, and almost always it affords me a much better grasp on the subject.

Actually sitting down and writing code seems like the best way to learn, on the surface. I can get too caught up in it though and instead of learning anything about the language or the design, I just fall back on the three or four simple concepts I know and plug away. It’s not a totally bad thing, but I need to keep pushing myself forward. I have been learning a lot of advanced techniques, I just have to force myself to start using them. Lambdas and closures and currying and all of the beautiful things about first class functions, all that stuff is rolling around in my head. The sooner I put it in my codebase, the sooner I can really understand it.

For me, “hitting the books” covers actually reading books, as well as perusing documentation and other people’s code, and especially, it means things like freeCodeCamp, Codecademy and Code School. In the last week or so, I revisited the level 1 Angular course at Code School (give it a shot, that class and several others are free) and then used the momentum to finish their just-released level 2 Angular course. I also jumped back into their JavaScript courses. I had stalled out midway through level 3. It is some pretty heady stuff, but I realized that I shouldn’t back off every time something gets tough. So, last night at about 10:30 PM, I finished the last exercise with some fun prototyping tricks.

My friend Chris Gomez pointed me at an article by Eric Elliot that shines some light on a few ways JavaScript really gets it right. It’s an interesting article that everyone learning to program, for web especially, should probably read. I realized that I own his book, “Programming JavaScript Applications,” and so, after reading the article, I cracked the book open and dove in. It is definitely not beginner level reading, but it isn’t so advanced as to be unreachable. I’ve only been doing this for a few months, and although some of the concepts are still not totally transparent, he does a great job of explaining everything. It also dispenses with the (boring) beginner stuff that you’ve probably read in the first three chapters of every other JavaScript text you’ve looked at. He is concise and knowledgeable, and his style is approachable and very readable. I have a feeling this is going to be a great reference book for me while I incorporate “real” programming methods into my repertoire.

Next up, I want to try the Best Practices course at Code School and jump back into the challenges at freeCodeCamp. I also want to continue my series on Test-Driven Development and finish up my blackjack game. I hope everyone has a productive and happy March!

Advertisements

More TDD: Chipping Away

Over the past few days I have been using chunks of free time to figure out which tests to write next. In the last post, I was a little frustrated with the process, but almost immediately I found a groove and a style of writing tests that has been pretty productive. One of the biggest steps forward was to stop worrying about everything so much. The important thing is that I am trying, and I am moving forward. With that mental block out of the way, I got busy.

With setting up a shoe and dealing hands out of the way, I knew I needed a way to score the hands, so I built a test for a scoreHand function. Usually each test block, wrapped in an ‘it’, will have a couple of tests. Sometimes it will have more. They don’t start this way, I try to start each one with one test case, like this:

describe('scoreHand', function(){
    it('should check the dealerHand score', function(){
        assert.equal(scoreHand([5,5]), 10);
});

Eventually they grow larger. I try to encompass edge cases if I can think of them and both pass and fail cases where applicable. Currently, the scoreHand test is a medium sized test (for me) and it looks like this:

describe('scoreHand', function(){
    it('should check the dealerHand score', function(){
        assert.equal(scoreHand([5,5]), 10);
        assert.equal(scoreHand([10,8]), 18);
        assert.equal(scoreHand([3,5,8,2]), 18);
        var testHand = [6,5,10];
        assert.equal(scoreHand(testHand), 21);
    });
});

An example of a simpler test case is the very next test, testForBlackjack. I envision using this test just after the initial deal to determine if anyone has a blackjack. Simple function, simple test:

describe('testForBlackjack', function(){
    it('should check for 21', function(){
        assert.equal(testForBlackjack(scoreHand([10,11])), true);
        assert.equal(testForBlackjack(scoreHand([5,5])), false);
    })
});

Occasionally a test gets longer, and sometimes more complicated. I am learning to take this as a warning sign. It tells me that either I am trying to do too much with one test or too much with one function (or both). It can also start to feel brittle, too reliant on some not-quite-hashed-out syntax. A great example of that is my dealCard test and function:

describe('dealCard', function(){
    it('should deal one card to the correct player', function(){
        dealCard("player");
        assert.equal(playerHand.length, 3);
        assert.equal(shuffledShoe.length, 47);
        dealCard("player");
        assert.equal(playerHand.length, 4);
        assert.equal(shuffledShoe.length, 46);
        dealCard("dealer");
        assert.equal(dealerHand.length, 3);
        assert.equal(shuffledShoe.length, 45);
    })
});

I do not like the parameter I am passing, and I know I will have to rewrite the test when I clean up (redesign vs. refactor) the function. In fact, looking at the function again, I hate it even more. I will have to give that part of the code some attention soon.

Along the way, I did have an “ah-ha” moment with TDD, especially about the “Driven” part, so I made a little screencast about it for my YouTube channel. The video is up here, and I will talk about that in more detail in a later post, along with a neat bit of coding I learned thanks to WebStorm. As always, I try to keep my code up to date in my GitHub repositories, so if you want to look at the guts, blackjack is right here. Comments, questions and criticism welcome!

TDD part 3: Arrrrrrrrrrrrrrrrrrrrrgh

Testing is… not going perfectly. I’m not even sure it is going well. I can make the tests work. The asserts and whatnot are real, they check the right things, and they pass. But the format of my tests is starting to suck. I am sure this is due partially to my lack of familiarity with the testing syntax and partially to my lack of basic JavaScript knowledge, but that doesn’t make it any less frustrating.

This is what I mean by sucky syntax:

it('should have removed four cards from the shuffledShoe and dealt the right cards out', function(){
    var shuffledShoe = shuffleShoe(makeShoe(1));
    var card1 = shuffledShoe[0];
    var card2 = shuffledShoe[1];
    var card3 = shuffledShoe[2];
    var card4 = shuffledShoe[3];
    assert.equal(48, initialDeal(shuffledShoe).length);
    assert.equal(card1, playerHand[0]);
    assert.equal(card2, dealerHand[0]);
    assert.equal(card3, playerHand[1]);
    assert.equal(card4, dealerHand[1]);
});
it('should deal two cards each to the player and the dealer', function() {
    assert.equal(2, playerHand.length);
    assert.equal(2, dealerHand.length);
     //need to figure out this set of tests
 //
});

I want to do this right, I just haven’t been able to hack my way into right yet. I’ve tried assigning the variables outside the it block but in the describe block. I have tried a beforeEach block. I don’t know what to try next. I’ll keep trying though!

The other thing I struggle with is a question of granularity. Are my tests granular enough? Too granular? Should I be testing everything? I don’t know the answers to those questions either. One day I hope to be able to use this post as a kind of reminder of what it was be like to be honestly ignorant. To hopefully remember that, there really are very few stupid questions.

The nice thing is, my test results look like this:

Blackjack Game
 deck
 √ should exist 
 √ should have a length of 52 
 makeShoe
 √ should be a function 
 √ should have a length equal to deck*numberOfDecks 
 shuffleDeck
 √ should return a shuffledShoe the same length as the shoe 
 initialDeal
 √ should have removed four cards from the shuffledShoe and dealt the right cards out 
 √ should deal two cards each to the player and the dealer
 7 passing (14ms)

Intentionally Writing The Wrong Code

I decided to document the process of TDD with a short screencast that includes the first few steps of the TDD process. In the video, I write a failing test, write code that doesn’t pass, and then write “bad” code that makes the test pass. I’m hoping to demonstrate the principle, as I understand it, of writing the simplest code that makes a test pass. The last step in the video is writing an additional test that exposes the weakness of my simple code and will put me on the path to writing functional code. It’s just a few minutes long, but I suggest you watch in in HD (at least 720) and full screen, if you want to be able to read the code.

Test-Driven Development, part 2

Let me start off by saying, I’m new, I don’t know what I’m doing, and it is always possible I am a little wrong, a lot wrong, or even all the way wrong…

My understanding of Test-Driven Development is this: Start from scratch, write a failing test, run the test, write the simplest code that will make the test pass, write another test, etc. There is some nuance there that is hard to put into words but easier to put into practice. Usually your second failing test will require rewriting your simplest code from the first failing test into actual working code. Also, you want to keep writing tests about the same general thing until you are satisfied that thing is finished (or as finished as you need it for now). There will be some examples shortly.

I decided that I needed a very concrete and simple project to help me wrap my head around TDD. I have chosen to build the game of blackjack, with one player and the dealer. A fairly simple game with simple requirements. The dealer doesn’t even need “real” A.I. because the rules dictate the actions the dealer must take. If one is to think about how to go about playing a game of blackjack, it becomes very easy to list the steps in order. My list looks like this:

  1. Produce one or more decks of cards
  2. Combine those decks into a shoe of cards
  3. Shuffle the shoe
  4. Initial deal, 2 cards, player first
  5. Check for dealer blackjack
  6. Player input, check for bust
  7. Dealer takes cards as per the rules, check for bust
  8. Determine winner

For now I am not including betting. Point 6 breaks down into another list of choices like split and doubling down. But that’s the broad outline, and the order in which I think I am going to tackle the programming. So the first step is to have a deck. At this point I have no code at all, which means it is the perfect time to write my first test!

(I’m using mocha and node.js’s assert style. To get assert in there I added this line of code

var assert = require("assert");

)

The whole thing gets wrapped in a describe block, and then each logical separation gets a nested describe block too. Inside of those are the it blocks, the tests themselves:

describe('Blackjack Game', function(){
    describe('deck', function(){
        it('should exist', function(){
            assert.equal(typeof deck, 'object');
        });
    });
});

There it is. In the command line, I type “mocha”, hit enter and I get…

Blackjack Game
deck
1) should exist

1 failing

1) Blackjack Game deck should exist:
AssertionError: ‘undefined’ == ‘object’

Just the failing test I was looking for. I haven’t created deck, or anything else yet. Let’s fix that.

var deck = [];

Re-run the test, it passes!

Blackjack Game
deck
√ should exist

1 passing

That was simple, but that deck is empty, we wouldn’t play with an empty deck, would we? We need a deck that has 52 cards, let’s test that.

it('should have a length of 52', function(){
    assert.equal(deck.length, 52);
});

And of course, that test fails. Remember, failing is a good thing! So I filled the deck array up with 52 members. On some level it is probably important to know what those members are and to test against that as well, but I took the liberty of moving on. I can always come back once that is important.

In the same way, I wrote tests for the shoe and then built the shoe to make the tests pass. This image from my last post has the whole set of tests:

mocha

I lumped a set of three “subtests” into one test that checks that the decks add up to the right number of cards. I don’t know if that is the right way to do it, but it works well enough. Below is the totality of the blackjack code I have written so far. Not very impressive, but it all does exactly what I want it to do, for now. Next up is shuffling the shoe. I have to figure out how I am going to test that and then how I am going to actually shuffle. I copied a shuffling algorithm from a stack overflow post a few days ago that I know works, but I didn’t really understand how. I need to sit down with that for a while and see if I can make sense of it. I think the test I will have to compare, somehow, the starting shoe array against the shuffled shoe array. The details elude me, but I am working on it!

testedCode

Test-Driven Development

(Fun fact, I looked up capitalization rules for hyphenated words in titles. I was going to capitalize Driven no matter what since it is the first D in TDD, but I thought it would be interesting to know the proper grammar)

I feel like testing in general and test-driven development in particular might be a very polarizing subject for some. Maybe being new to the field helps me have a much more blasé attitude toward the topic. Maybe, for once, my naivety is working in my favor. Or perhaps I am strolling blindly down the biggest primrose path in programming. Only time will tell!

Today I wrote my first ever tests. I even started with a blank slate of a program and made sure that every test fails the first time around. Some of them continue to fail after that first time. Eventually I get them to pass. I’m even up to four tests! It has been an interesting process.

Like everything else in learning to program, the first step is the most daunting. There are so many choices. And, once again, my knowledge and ability isn’t really up to evaluating the choices… at all. So, I turned to Google. Having just purchased WebStorm, I thought it would be a good idea to see what integrates well there. That lead me to some WebStorm documentation (here) that narrowed my choices down. Kind of. It now looked like I needed to pick a test runner AND a unit testing framework. Well, ok. On the list for test runners are:

When I was looking at all this, last night, all of these names were new to me. I dug further into the docs and it looked like Karma had the most extensive write-up, so I chose it. First step to installation was installing node.js, because everything else from here on out would be installed using npm, the node package manager. From there you get some choices. You cna use WebStorm’s GUI to select packages from a list or go straight for the command line. It’s the same process for the frameworks, here are the choices:

I had actually heard of (and did surface research on) both QUnit and Jasmine before, so I thought I would try those out. I spent a while typing away on the command line and getting everything setup and then the moment of truth… how in the world do I actually write my tests? It was pretty late by the time I got all of this accomplished so I decided to get a fresh start in the morning.

What really happened was, I had a long talk with my friend Chris about testing and he even showed me how he got it working in Visual Studio. We went over some tests and the ideas of writing an initially failing test and some of the philosophy behind TDD. In some ways, he is almost as new to testing as I am, so it is interesting to get a grizzled veteran’s take on the whole thing. When that was over, it was really bedtime, and my brain was fried anyway, so off to dreamland I went.

This morning I cleaned out my project and started from fresh. I looked at the WebStorm docs some more and looked at other testing docs, specifically Mocha’s. It actually looked pretty simple to set up, and it turns out I can use it without a test runner, so for the sake of actually getting something done, I gave it a shot. At first, it was pretty hairy. There are still pieces of the puzzle missing for me, so I just copied chunks of the tutorial to get things working. I got tests working to some degree, but I kept (and continue to keep) banging up against the edges of both my comfort zone and my actual knowledge base.

I’m not entirely happy with the details of how I have mocha running, but for now, I am prioritizing having it working over having it working just right. Here is the fruits of my labor:

mochaThe tests are on the top and the result on the bottom. Four passing tests! I really have no idea if my tests are too simple or too complex or if I am using the correct syntax, or a million other things that point out my already completely obvious newness to programming. I am learning to get over the nervousness about exposing my ignorance. I will sometimes post stupid example or ask stupid questions, and I have to be ok with that.

In my next post, I will dive more into the details of how I got this all working and the steps I took once I had it working to jump into the TDD way of doing things. As always, I’m always happy to answer questions or explain specific nuances of my process. Thanks for taking the time to read this and, keep coding!