UNB/ CS/ David Bremner/ teaching/ cs2613/ labs/ Lab 12

Background

Overview

This lab and the next are based on Chapter 8 of the Second edition of Eloquent JavaScript. We'll get about half way through today, and finish it off on Thursday.

Classes again

Time
20 minutes
Activity
Small Groups
    let life=require ("../life.js");

    describe("Grid",
        function() {
            let Vector = life.Vector;
            it("initially undefined",
                function() {
                    let grid = new life.Grid(5, 5);
                    expect(grid.get(new Vector(1, 1))).toBe(undefined);
                });
            it("setting a value",
                function() {
                    let grid = new life.Grid(5, 5);
                    grid.set(new Vector(1, 1), "X");
                    expect(grid.get(new Vector(1, 1))).toEqual("X");
                });
        });

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.

    describe("BouncingCritter",
         function() {
             it("constructor",
                function() {
                    let bob=new life.BouncingCritter();
                    expect('direction' in bob).toBe(true);
                    expect(bob.direction).toBe('s');
                });
         });
        spyOn(Math, 'random')._____________________;
    describe("BouncingCritter",
             function() {
                 let 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');
                    });
            });

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() {
                        let plan = ["############################",
                                    "#      #    #      o      ##",
                                    "#                          #",
                                    "#          #####           #",
                                    "##         #   #    ##     #",
                                    "###           ##     #     #",
                                    "#           ###      #     #",
                                    "#   ####                   #",
                                    "#   ##       o             #",
                                    "# o  #         o       ### #",
                                    "#    #                     #",
                                    "############################"];
                        let 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.

    let test = {
      prop: 10,
      addPropTo: function(array) {
        return array.map(function(elt) {
          return this.prop + elt;
        });
      }
    };
    console.log(test.addPropTo([1,2,3]));
    function lala(arg1,arg2){
        return(this.name+arg1+arg2);
    }

    console.log(lala.call({name: "spongebob"}, " square", "pants"));
    Grid.prototype.forEach = function(f, context) {
      for (let y = 0; y < this.height; y++) {
        for (let x = 0; x < this.width; x++) {
          let value = this.space[x + y * this.width];
          if (value != null)
            f.call(context, value, new Vector(x, y));
        }
      }
    };
        it("forEach",
           function() {
               let 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);
           });