Week 6, Part 2: Fortnight of Fashioning: Better Webpages

blacksmith

Other memorable lessons over the last two weeks revolve around web design. I’ve learned a great deal about using HTML since teaching it over a decade ago! For instance, HTML should only define the information that will be present on a webpage, as well as to divide and label important elements. The CSS file is incredibly powerful in its ability to create the aesthetics and to modify the overall appearance of a webpage quickly. Its effectiveness depends upon how well structured and labeled the HTML elements are written. jQuery completes the trifecta, and in combination with CSS definitions, can allow for easy manipulation of elements on the screen. The best implementation I’ve witnessed of this feature involved a CSS that defined classes that didn’t yet exist on a webpage; but by using jQuery, classes can easily be removed or added. As a result, stylistic changes declared solely in the CSS file come into being when jQuery drives these changes, manipulating associated elements with one or more classes via scripting.

The browser inspect tool, found within the developer console of any browser, has turned out to be a greatly prized weapon in fighting the war of HTML element identification. It can also be helpful in tracking changes that are happening in realtime to any HTML file as a result of JavaScript. The console permits various adjustments to the HTML elements in realtime, allowing for experimentation and CSS tweaking before copying those changes to source. This sure beats making edits and then reloading the page file every time a change is made to the HTML or CSS file!

All in all, learning continues at an appropriate pace, practical tools are added daily to my toolbox, and overall confidence grows in wielding these tools for good. I can’t think of a better place to be in, given that today marks the half-way point for the course! I cannot wait to see what revelations will take place over the next six weeks!

Weeks 6, Part 1: Fortnight of Fashioning: SQL Injections

tools

It’s been two weeks since reporting in, and so much has transpired in such a short period of time! Our class has thoroughly explored data persistence and management leveraging PostgreSQL databases via JDBC; styled and created webpages that implement CSS and HTML5; and lately we have begun to harness jQuery to create interactive and interesting web pages. All in all, a lot of tools have been added to the proverbial toolbox, and I feel fantastic about approaching many personal programming projects that have fallen by the wayside in the past.

From a security standpoint, we learned early on to ward against SQL injection attacks using prepared statements, as well as the importance of locking down queries performed against an existing database. This conjured memories regarding a student whom I read about last year.

droptable

For those that don’t get the joke, a standard SQL query to retrieve this kid’s name for the yearbook cell could look something like:

"SELECT name FROM Students WHERE cellID=('" + student.name + "')";

Injecting the text above, the syntax would read:

"SELECT name FROM Students WHERE cellID=('" + "); DROP TABLE Students; -- + "')";

Which really would translate to the computer as:

SELECT name FROM Students WHERE cellID=('); 
DROP TABLE Students; 
-- + "')"

Reading this line by line would go something like:

  1. Return results where student id = ?; (ignore/returns empty result set)
  2. Delete the Student table; (crying happens here)
  3. Commented out (– denotes a comment, ignore this as garbage!)

The take-away lesson is to always use prepared statements to avoid any chance of an injection attempt. It appears this yearbook’s software did just that, albeit to the dismay of the student above. We will leave on a similar food-for-thought illustration with the legendary Bobby Tables.

bobbytables
Source: https://xkcd.com/327/

Week 4, Part 2: Parameterized Testing

Sliders

Parameterized Testing

Test-driven development is all the rage these days. However, it can become quite tedious to write multiple separate in-line tests that with nearly identical configurations, differing only in test data being fed and the anticipated result. Enter parameterized testing. Drastically reducing the time needed to write almost identical code test blocks, parameterized testing allows coders to quickly ascertain if their code revisions broke existing code, without the undesirable side-effect of having to code out each individual test case separately. By feeding one code test block a list of data and the expected results, the same test can be recycled multiple times, to ensure that all edge cases can be considered.

To begin cosing my test class, I found the Pragmatists library (pl.pragmatists:JUnitParams v1.0.5, at time of writing) to be an incredibly valuable resource in allowing specificity in my parameters for each individual test. In addition to this library, JUnit4 will also need to be imported. Hamcrest libraries never hurt for assertions, as well. After creating the test class in my Test root folder, I made sure my import statements were as follows:

import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.*;

Next, we’ll want to make appropriate usage of Annotations (@RunWith, @Test, and @Parameters) with proper defined syntax and correct body placement. A second method will also need to be created, name in the format “parametersForXXX”, which instantiates a 2D array of Objects, a collection of Objects holding a collection of Objects. This will hold each of our test case parameters. Consider the following example Logic2Test below:

@RunWith(JUnitParamsRunner.class)
public class Logic2Test {
    //makeBricks Tests
    @Test
    @Parameters
    public void makeBricksTest(int int1, int int2, int int3, boolean expectedResult) {
        //Arrange (Bump)
        //Act (Set)
        boolean methodResult = Logic2.makeBricks(int1, int2, int3);
        //Assert (Spike)
        assertThat(methodResult, is(equalTo(expectedResult)));
    }

    private Object[] parametersForMakeBricksTest() {
        return new Object[][]{
                {3, 1, 8, true},
                {3, 1, 9, false},
                {3, 2, 10, true},
                {3, 2, 8, true},
                {3, 2, 9, false},

                {40, 2, 52, false},
                {22, 2, 33, false},
                {0, 2, 10, true},
                {1000000, 1000, 1000100, true},
                {2, 1000100, 100003, false},
        };
    }
}

It is important to note that the method being tested was made static in order to test it. Here is the Logic2 Class file the above test is evaluating:

public class Logic2 {

    public static boolean makeBricks(int small, int big, int goal) {
        final int SMALL = 1;
        final int BIG = 5;
        int largestPossible = small*SMALL + big*BIG;
        if(largestPossible < goal) {
            return false;
        } else {
            for(int i = big; i >= 0; i--) {
                for(int x = small; x >= 0; x--) {
                    if(((i*BIG) + (x*SMALL)) == goal) {
                        return true;
                    }
                }
            }
            return false;
        }
    }
}

One very important footnote: evaluating collections can be a pain, including Arrays, ArrayLists, and/or HashMaps. Simply declare and initialize the collection prior to declaring it in the parameterized list in order to use it during testing. A modest example for consideration is posted below:

private Object[] parametersForArrayTest() {
    int[] array1 = new int[]{1, 2, 3};
    int[] array2 = new int[]{4, 5, 6};
    int[] array3 = new int[]{7, 8, 9};

    return new Object[][]{
            {array1, true},
            {array2, false},
            {array3, true},
    };
}

Week 4, Part 1: Data Persistence

DataImg

After a few weeks of radio silence, I am pleased to report that I’ve been able to take away a few valuable nuggets that I wanted to share, in the hopes that it helps others looking for answers.

Data Persistence

Converting between Java objects and JSON string representations can make data management easier when storing to disk or reading from disk. This can really save your bacon when you are not dealing with easily serializable data or comma/space delimited data.

Let’s say for example you have an Animal object with four properties that you wish to write to disk. This is easily done by leveraging the GSON library import (com.google.code.gson:gson v2.7, at the time of writing), and executing:

Animal frog = new Animal("Fred", "Frog", "Poison Dart", "Green");
String jsonAnimal = new Gson().toJson(frog);

When the string is output to console, we receive:

{"name":"Fred","species":"Frog","breed":"Poison Dart","description":"Green"}

To process a pre-generated Json string back into an object:

String jsonAnotherAnimal = "{\"name\":\"Tony\",\"species\":\"Tiger\",\"breed\":\"\",\"description\":\"Greeeeaatttt!\"}";
Animal anotherFrog = new Gson().fromJson(jsonAnotherAnimal, Animal.class);

When the animal is output to console using a custom toString method:

Name: Tony
Species: Tiger
Breed:
Description: Greeeeaatttt!

This is well and great if you have a small number of objects. When considering more complex data structures, this simply will not cut the proverbial mustard. Let’s consider that I have an collection of Animal objects organized by continent in a HashMap. To process this tiered data structure, Type will be needed to define how to process the data.

String jsonAnimalsByContinent = "{\"Australia\":[{\"name\":\"Kate\",\"species\":\"Koala\",\"breed\":\"\",\"description\":\"Shy\"},{\"name\":\"Wally\",\"species\":\"Wallaby\",\"breed\":\"\",\"description\":\"Savage\"},{\"name\":\"Evan\",\"species\":\"Emu\",\"breed\":\"\",\"description\":\"Aggressive\"}],\"North America\":[{\"name\":\"Bianca\",\"species\":\"Bear\",\"breed\":\"Kodiak\",\"description\":\"Brown\"}]}";
Type listType = new TypeToken<HashMap<String, ArrayList<Animal>>>(){}.getType();
HashMap<String, ArrayList<Animal>> result = new Gson().fromJson(jsonAnimalsByContinent, listType);
System.out.println(result.get("Australia"));

This produces the desired result:

[
 Name: Kate
 Species: Koala
 Breed:
 Description: Shy ,
 Name: Wally
 Species: Wallaby
 Breed:
 Description: Savage ,
 Name: Evan
 Species: Emu
 Breed:
 Description: Aggressive ]