UNB/ CS/ David Bremner/ tags/ life

This feed contains pages with tag "life".

Background

Overview

In this lab we will start to work our way through Eloquent JavaScript Ch. 7. We'll get about half way through today, and finish it off on Thursday.

Classes again

Time
20 minutes
Activity
Small Groups
  • Create a file ~/fcshome/cs2613/labs/L12/life.js, and copy the code from Representing Space. Add appropriate exports.

  • Save the following Jasmine tests in ~/fcshome/cs2613/labs/L12/life.spec.js and verify that they pass.

    var life=require ("./life.js");

    describe("Grid",
        function() {
            var Vector = life.Vector;
            var grid = new life.Grid(5, 5);
            it("initially undefined",
                function() {
                    expect(grid.get(new Vector(1, 1))).toBe(undefined);
                });
            it("setting a value",
                function() {
                    grid.set(new Vector(1, 1), "X");
                    expect(grid.get(new Vector(1, 1))).toEqual("X");
                });
        });
  • Convert life.js to ES2015 class style. See Lab 11 for an example. You should end up two classes, Vector and Grid. Verify that the (unchanged) tests still pass.

Mocking.

Time
30 minutes
Activity
Small Groups

Writing unit tests is easiest when developing code from the bottom up. That's not always the most natural way to write a program (and rarely the most natural way to design one). For this reason we need strategies to develop tests when the some or most of the code is not written yet.

  • Copy the code for A critter’s programming interface

  • This code presents several challenges for our test-as-we-go philosophy. First, let's try to test the constructor for BouncingCritter. Observe that the constructor test fails often (it might succeed once in a while just by chance). This is because of the use of Math.random.

    describe("BouncingCritter",
         function() {
             it("constructor",
                function() {
                    var bob=new life.BouncingCritter();
                    expect('direction' in bob).toBe(true);
                    expect(bob.direction).toBe('s');
                });
         });
  • Unfortunately JavaScript doesn't provide a way to seed Math.random (so it produces the same sequence of numbers for every test run). The usual suggestion is to replace the random number generator with one that allows a seed. As a "QA person", you might not be allowed to change the code you are testing; luckily Jasmine supports a concept called mocking, which essentially allows replacing functions for use by the test suite. Use a Jasmine spyOn to force Math.random to always return 0.5 in the constructor test. Add a call like the following before the definition of bob
        spyOn(Math, 'random')._____________________;
  • We still need to test our act method. We can see from reading the code that it takes an object with methods look and find. This allows us to do mocking for act just by passing in appropriate objects. On the other hand we still need to reproducibly create a test critter, so so let's factor out the setup using beforeEach; The modified describe group should look something like
    describe("BouncingCritter",
             function() {
                 var bob = null;
                 beforeEach(function () {
                     spyOn(Math, 'random').____________________;
                     bob=new life.BouncingCritter();
                 });
                 it("constructor",
                    function() {
                        expect('direction' in bob).toBe(true);
                        expect(bob.direction).toBe('s');
                    });
            });
  • Add a second test which tests act with a view object such that view.look always returns " ". You don't need to use spyOn for this or the next point.

  • Add a third test which tests act with a view object such that view.look always returns "#", and view.find always returns "n"


World objects

Time
20 minutes
Activity
Small Groups

Copy the World Object code from the book and complete the following test for the World constructor and toString. One potentially tricky point will be the final newline in the output of toString.

    describe("World",
             function () {
                 it("roundtrip",
                    function() {
                        var plan = ["############################",
                                    "#      #    #      o      ##",
                                    "#                          #",
                                    "#          #####           #",
                                    "##         #   #    ##     #",
                                    "###           ##     #     #",
                                    "#           ###      #     #",
                                    "#   ####                   #",
                                    "#   ##       o             #",
                                    "# o  #         o       ### #",
                                    "#    #                     #",
                                    "############################"];
                        var world = new life.World(plan, {"#": life.Wall, "o": life.BouncingCritter});



                    });
             });

The this trap

Time
30 minutes
Activity
Demo / Group discussion

The magical variable this gets a new binding for each function. Since typical JavaScript uses many inner functions, this tends to mean the this object you care about gets shadowed.

  • Run the following code in the code-oss debugger, observing the value of this in the inner loop.
    var test = {
      prop: 10,
      addPropTo: function(array) {
        return array.map(function(elt) {
          return this.prop + elt;
        });
      }
    };
    console.log(test.addPropTo([1,2,3]));
  • Use the var self=this trick to fix the code.

  • A fancier technique uses the call method of a function. Run the following code in the debugger:

    function lala(arg1,arg2){
        return(this.name+arg1+arg2);
    }

    console.log(lala.call({name: "spongebob"}, " square", "pants"));
  • Add the following code (first line transformed appropriately) to your ES2015 class declaration for Grid.
    Grid.prototype.forEach = function(f, context) {
      for (var y = 0; y < this.height; y++) {
        for (var x = 0; x < this.width; x++) {
          var value = this.space[x + y * this.width];
          if (value != null)
            f.call(context, value, new Vector(x, y));
        }
      }
    };
  • Here is a test to illustrate the use of the new forEach method. Add it to life.spec.js. Notice the passing of this as a second argument to forEach.
        it("forEach",
           function() {
               var test = {grid: grid,  sum: 0,
                           method: function () {
                               this.grid.forEach(function() { this.sum++; }, this);
                           }
                          };

               test.grid.set(new Vector(2,3), "#");
               test.grid.set(new Vector(3,4), "#");
               test.method();
               expect(test.sum).toBe(3);
           });
Posted Tue 17 Oct 2017 11:30:00 AM ADT Tags: /tags/life

So last night I did something I didn't think I would do, I bought an downloadable album in MP3 format. Usually I prefer to buy lossless FLAC, but after a good show I tend to be in an acquisitive mood. The band was using isongcard.com. The gimick is you give your money to the band at the show and the give you a card with a code on it that allows you to download the album. I can see the attraction from the band's point of view: you actually make the sales, rather than a vague possibility that someone might go to your site later, and you don't have to carry crates of CDs around with you. From a consumer point of view, it is not quite as satisfying as carting off a CD, but maybe I am in the last generation that feels that way.

At first I thought this might have something to do with itunes, which discouraged me because I have to borrow a computer (ok, borrow it from my wife, downstairs, but still) in order to run Windows, to run itunes. But when I saw the self printed cards with hand-printed 16 digit pin numbers, I thought there might be hope. And indeed, it turns out to be quite any-browser/any-OS-friendly. I downloaded the songs using arora, and they are ready to go. I have only two complaints (aside from the FLAC thing).

  • I had to download each song individually. Some kind of archive (say zip) would have been preferable.

  • The songs didn't have any tags.

So overall, kudos to isongcard (and good luck fending off Apple's lawyers about your name).

Posted Sat 08 Aug 2009 09:16:00 AM ADT Tags: /tags/life

Apparently a 90 m2 appartment in Ulaanbaatar goes for USD600 a month. No offence to the residents of Ulaanabaatar, but that seems pretty expensive to me. The things you learn from spam.

Posted Fri 27 Jun 2008 12:00:00 AM ADT Tags: /tags/life