Unit Testing

Unit testing is when you write a test for each unit (or each function/method) in a program. Each unit test is made up of assertion statements.

assertEqual: This can only be used to check scalar values (numbers or strings), not objects or arrays.

Screen Shot 2017-03-15 at 11.44.50 AM

assertWithinRange: This checks if output is within a certain range.

Screen Shot 2017-03-15 at 11.46.12 AM

assertArraysEqual:  To assert that two arrays are equal, you must first check that they’re both equal in values and lengths.

Screen Shot 2017-03-15 at 11.41.14 AM

assertObjectsEqual: objects must be converted to strings first to be compared.

Screen Shot 2017-03-15 at 11.45.51 AM

How to call an assertion:

assertEqual(findLongestPalindrome('racecar hannah'), 'racecar', 'finds longest of two palindromes');
Unit Testing

Some Array Methods

var newArray= Array.from(oldArray);

var newArray = oldArray.slice(); 

Makes a new copy of the old array instead of just referencing it.


Array.isArray(input); 

Checks if a value is an array.


arr.slice(begin, end);

Extracts a portion of an array based on provided indices. (Omitting begin will default it to index 0.  Omitting end will default to extracting up to the end arr.length).


arr.splice(startIndex, deleteCount, ‘item1‘, item2‘, etc.);

Remove or insert element where start is.  (Set deleteCount to 0 if you’re inserting).

Some Array Methods

Big O

Big O notation describes the performance or complexity of an algorithm.

Screen Shot 2017-03-09 at 12.12.04 PM

O(1) – Constant time complexity – describes an algorithm (a one-line statement code) that will always execute in the same time (or space) regardless of the size of the input data set. An example is accessing a value of an array.

var arr = [ 1,2,3,4,5];
arr[2]; // => 3

 

O(N) – Linear time complexity – describes an algorithm (usually a loop) whose performance will grow linearly and in direct proportion to the size of the input data set. For example, if the array has 10 items, we have to print 10 times. If it has 1,000 items, we have to print 1,000 times.

//if we used for loop to print out the values of the arrays
for (var i = 0; i < array.length; i++) {
  console.log(array[i]);
}

 

O(log N) – Logarithmic time complexity – describes an algorithm where have a large set of data and you halve the dataset at each iteration until you get the result that you’re looking for.  An example of this is finding a word in a dictionary (binary search).   Sorting a deck of cards (merge sort) would be O(N log N).

Other examples:

Example 1:
for (var i = 1; i < n; i = i * 2)
  console.log(i);
}
Example 2:
for (i = n; i >= 1; i = i/2)
 console.log(i);
}

 

O(N2) – Quadratic time complexity – represents an algorithm whose performance is directly proportional to the square of the size of the input data set. This is common with algorithms that involve nested iterations over the data set. Deeper nested iterations will result in O(N3), O(N4) etc.  Examples include checking for duplicates in a deck of cards, bubble sort, selection sort, or insertion sort.

for(var i = 0; i < length; i++) {     // has O(n) time complexity
    for(var j = 0; j < length; j++) { // has O(n^2) time complexity
      // More loops?
    }
}

 

O(2N) – Exponential time complexity – denotes an algorithm whose growth doubles with each addition to the input data set. An example of an O(2N) function is the recursive calculation of Fibonacci numbers.  Another example is trying to break a password by testing every possible combination (assuming numerical password of length N).

Amortized time: 

If you do an operation say a million times, you don’t really care about the worst-case or the best-case of that operation – what you care about is how much time is taken in total when you repeat the operation a million times.

So it doesn’t matter if the operation is very slow once in a while, as long as “once in a while” is rare enough for the slowness to be diluted away (that the cost is “amortized”).  Essentially amortised time means “average time taken per operation, if you do many operations“.

Source: stackoverflow

Space complexity: 

Sometimes we want to optimize for using less memory instead of (or in addition to) using less time. Talking about memory cost (or “space complexity”) is very similar to talking about time cost and we also use the Big O notation.

Big O Cheatsheet.

Big O

OO Programming vs Functional Programming

In all programs, there are two primary components: the data (the stuff a program knows) and the behaviors (the stuff a program can do to/with that data).

Object-Oriented Programming: programming paradigm that brings together data and its associated behaviors (functions) in a single location called an “object”.

  • data structure is usually an array of objects.  (Data is converted into objects and methods are called on them).

Example:

class Employee
  def initialize(name, salary)
    @name = name
    @salary = salary
  end

  def change_salary(amt)
    @salary = @salary + amt
  end

  def description
    "#{@name} makes #{@salary}"
  end
end
employees = [
  Employee.new("Bob", 100000.0),
  Employee.new("Jane", 125000.0)
]

employees.each do |emp|
  emp.change_salary(10000.0)
end

employees.each do |emp|
  puts emp.description
end

Functional Programming: programming paradigm that says data and behavior are distinctively different things and should be kept separate for clarity.

  • data structure is an array of arrays and/or hashes to not *complicate* data by mixing it with behavior.
  • FP leans very heavily on tiny methods that do one small part of a larger job, delegating the details to other tiny methods. This combining of small methods into a larger task is call “composition”.
  • This idea of not changing the contents (or “state”) of a variable once it’s been created is called immutability and is another key aspect of FP.

Example:

employees = [
  [ "Bob",  100000.0 ],
  [ "Jane", 125000.0 ]
]
happier_employees = change_salaries(employees, 10000.0)
happier_employees.each do |emp|
  puts "#{emp[0]} makes #{emp[1]}"
end
OO Programming vs Functional Programming

debugger;

  1. Write debugger; as the first line inside your function.
  2. Inspect Element.
  3. Run the function in the Console and look at the Sources tab.  (The ‘debugger;‘ line should be highlighted in Sources).
  4. ‘Step over the next function call’ to test the code line by line as it’s running.
  5. ‘Step into the function’ if you want to go inside the callback function that’s inside the function you’re debugging.

* Create a separate function to run the debugger on any function instead of having to write debugger; in each of our function.

function runWithDebugger (ourFunction) {
    debugger;
    ourFunction();
}
debugger;

JS: Object (references) Comparison

When you create an object in Javascript, it stores the object at a unique location in memory.  So even when the objects look identical, they are not the same because JS is comparing to see if they are at the same memory address, not if they look the same or not.

Thus, {} === {}  would return false.

Notes: 

  • Values and variables of same type take same amount of fixed storage (allocated memory).
  • All objects, however, are not of the same size. When a new object is created, a composite memory block consisting of a series of consecutive blocks, one for each instance variable of the object, is created.  The sizes of two objects of different types can be different depending on the number and the types of their instances variables.
  • Since an object variable stores addresses, it also called a pointer variable or reference variable, and the address stored in it a pointer or reference.
JS: Object (references) Comparison