\documentclass[12pt,fleqn]{article}

\usepackage{url}
\usepackage{listings}

\setlength {\topmargin} {-.15in}
\setlength {\textheight} {8.6in}

\newcommand{\be}{\begin{enumerate}}
\newcommand{\ee}{\end{enumerate}}
\newcommand{\bi}{\begin{itemize}}
\newcommand{\ei}{\end{itemize}}
\newcommand{\bc}{\begin{center}}
\newcommand{\ec}{\end{center}}
\newcommand{\bsp}{\begin{sloppypar}}
\newcommand{\esp}{\end{sloppypar}}
\renewcommand{\labelenumii}{\theenumii.}

\input{../Comments}

\begin{document}

\bc

{\Large \textbf{SOFTWARE ENGINEERING 3XA3}}\\[2mm]
{\large \textbf{Software Engineering Practice \& Experience: Software Project Management }}\\[6mm]
{\large \textbf{Dr.~Spencer Smith}}\\[2mm]
{\large \textbf{McMaster University, Fall 2016}}\\[6mm]
{\LARGE \textbf{Laboratory 07 Unit Testing Frameworks}}\\[4mm]
{\large Revised: September 12, 2016}

\ec

\medskip

\noindent

%Assume students have no knowledge of the topic

% BEGIN INTRO SCRIPT

\subsection*{Components of Lab}

\be
\item Introduction to types of software testing

% BEGIN TESTING TYPES
%
% Unit testing (aka white-box testing) is centered on testing the smallest
%  logical unit of your code; typically this means a single function or method
% Integration testing (also known as end-to-end testing or black-box testing) is
%  a different style of testing where the entire system is tested at once
%
% Ex. Imagine testing for the ability to add a student to a course on mosaic.
%  In the code:
%
%     public boolean addStudent(Student student, Course course) {
%       if (course.isFull()) return False;
%       if (!student.hasPreReqs(course)) return False;
%       if (!student.hasScheduleConflict(course)) return False;
%       // etc...
%       // all checks pass
%       student.addCourse(course);
%       return true;
%  }
%
%  End-to-end test would look like this:
%    1. create a valid Student and Course object
%    2. call the addStudent method with those objects. Check the expected result
%  -> We're testing the FUNCTIONALITY of the system, without caring about HOW
%       that functionality is accomplished
%
%  Unit testing would look like this:
%    1. create a Course object
%    2. call the course.isFull() method. Check the result against your expected
%         result
%    3. repeat with other course objects
%    4. repate with the other indiviual methods
%  -> We're testing each INDIVIDUAL small method, without looking at the overall
%       functionality of the system
%
% Both kinds of testing are important
% Integration tests tell you something is wrong
% Unit tests tell where the problem is
%  Unit tests can't catch problems in the interfaces between different methods
%    In the example above, if course.isFull() returned an Integer instead of a
%    Boolean, the integration test would fail, but your unit tests would pass
%
% END TESTING TYPES

\item Introduction to test-driven development

% BEGIN TEST DRIVEN DEVELOPMENT
%
% Test driven development is a style of development focused on testing
%  (both unit testing and otherwise)
% Test driven development works as follows:
%  1. gather requirements for your feature/project
%  2. turn each requirement into an automated test
%  3. write code
%  4. run tests. If your tests fail, go back to step 3. 
%       If the tests pass, you're done.
%
% In the context of 3XA3 (this course), you'll be looking at the original
%  open source project that you chose to gather those requirements/tests
%    in some cases, the original project may already have implemented some tests
%    you'll need to recreate those tests in your chosen language
%  when all of your tests pass, you know that your code is functionally complete
%
% END TEST DRIVEN DEVELOPMENT

\item Introduction to unit testing frameworks

%
% Strictly speaking, you don't NEED to use a unit testing frameworks
%  you can write a script that just calls a bunch of your methods and throws an
%    error if the results are incorrect
%  This is essentially what unit testing frameworks DO; they just make it easier
%
% Most unit testing frameworks give you three main methods:
%  - A way to set up your system into the correct state
%  - A way to run your tests
%  - A way to clean up your system after tests have completed
% Typically unit testing frameworks will provide you with methods to check for
%   specific conditions. These provide better feedback than a simple assert
%   or just throwing an error.

% END INTRO SCRIPT

\item GitLab Exercises

\ee

\subsection*{Details}

\bi
\item There are two main types of software testing: Unit Testing and Integration
testing
\bi
\item Unit testing (aka white-box testing) is centered on testing the smallest
logical unit of your code; typically this means a single function or method

\item Integration testing (also known as end-to-end testing or black-box testing)
is a different style of testing where the entire system is tested at once

\item The following article goes into more detail about the kinds of testing:
\url{http://softwaretestingfundamentals.com/unit-testing/}
\ei

\item Test driven development is an iterative workflow where, the programmers
write unit and integration tests before they write any code. Then, after they
have finished a logical section of their code, they run the tests to see if they
have written the code correctly.

\item Most languages have some sort of testing framework, either as part of the
standard library (such as in Python) or as a third-party library (such as in
Java).

\bi
\item For today's lab, we will be providing examples in Python (2.7) and in Java.
If your team has decided on a different language, you must find and familiarize
yourself with that language's framework.

\bi
\item Documentation for Python 2's unittest:

\url{https://docs.python.org/2/library/unittest.html}
\item Documentation for Java's JUnit: 

\url{http://junit.org/junit4/}
\ei

\item Here are some tutorial videos for other languages:

\bi
\item Unit Tests in Visual C++ (For C and C++ languages):

\url{https://www.youtube.com/watch?v=2fxl7zMzfFM}
\item PHP-PHPUnit Testing (PHP):

\url{https://www.youtube.com/watch?v=Iq6wvboGU-A}
\ei

\item The JavaScript community hasn't settled on one ``best'' unit testing
framework; you'll have to choose one from the many that exist. Some suggestions:

\bi
\item Mocha: \url{http://mochajs.org}
\item Buster.JS: \url{http://docs.busterjs.org/en/latest/}
\item Jasmine: \url{https://github.com/jasmine/jasmine}
\item Ava: \url{https://github.com/avajs/ava}
\item and many more online...
\ei

\ei

\ei

\subsection*{Examples}

Suppose we had a Line2D class that modeled lines.
  This class has the following methods:
\bi
\item constructor \texttt{Line2D(float slope, float yIntercept)}
\item \texttt{float getY(float xValue)}
\item \texttt{float getX(float yValue)}
\ei

Our test cases would look like this:
\subsubsection*{Java}

\lstset{
  language=Java,
  showstringspaces=false,
  %columns=flexible,
  basicstyle={\small\ttfamily},
  numbers=none,
  numberstyle=\tiny\color{gray},
  keywordstyle=\color{blue},
  commentstyle=\color[rgb]{0.7,0.7,0.7},
  stringstyle=\color{red}
}
\begin{lstlisting}
import static org.junit.Assert.*;
import org.junit.BeforeClass;
import org.junit.Test;

public class LineTest {
    private static Line2D line;

    @BeforeClass
    public void setUp() {
        line = new Line2D(3, 2);  // y = 3x + 2
    }

    @Test
    private void testGetY() {
        // assertEquals is a JUnit method
        // the first arg (the string) is optional
        assertEquals("x value of 2 returns y value of 8",
line.getY(2),  8);
        assertEquals("x value of -2 returns y value of -4",
line.getY(2), -4);
        assertEquals("x value of 0 returns y value of 2",
line.getY(2),  2);
    }

    @Test
    private void testGetX() {
        assertEquals("y value of 5 returns x value of 1",
line.getX(5),  1);
        assertEquals("y value of -1 returns x value of -1",
line.getX(2), -1);
        assertEquals("y value of 0 returns x value of -2/3",
line.getX(2), (-2.0/3));
    }
}
\end{lstlisting}

\newpage
\subsubsection*{Python}

\lstset{language=Python}
\begin{lstlisting}
import unittest

class LineTest(unittest.TestCase):
    def setUp(self):
        self.line = Line2D(3, 2) # y = 3x + 2

    def testGetY(self):
        # assertEquals is a unittest method. 
        # the third arg (the string) is optional.
        assertEquals(line.getY(2),  8,
"x value of 2 returns y value of 8")
        assertEquals(line.getY(2), -4,
"x value of -2 returns y value of -4")
        assertEquals(line.getY(2),  2,
"x value of 0 returns y value of 2")

    def testGetX():
        assertEquals(line.getX(5),  1,
"y value of 5 returns x value of 1")
        assertEquals(line.getX(2), -1,
"y value of -1 returns x value of -1")
        assertEquals(line.getX(2), (-2.0/3), 
"y value of 0 returns x value of -2/3")

if __name__ == '__main__':
    # loadTestsFromTestCase looks for methods that 
    # start with the word "test"
    suite = unittest.TestLoader().loadTestsFromTestCase(LineTest)
    suite.run()
\end{lstlisting}

\newpage
\subsection*{Exercises}

\bi
\item On the gitlab repository hosting this document, you will find two files:
\texttt{Box3D.Java} and \texttt{Box3D.py}. Select the one that
corresponds to your prefered language.
\item Write tests to verify that the following methods work correctly:

\bi
\item \texttt{getDimensionsOfFace}: accepts a \texttt{Face} enum and returns the
dimensions of that face of the box.
\item \texttt{getAreaOfFace}: accepts a \texttt{Face} enum and returns the area
of that face of the box.
\item \texttt{getPerimeterOfFace}: accepts a \texttt{Face} enum and returns the
perimeter of that face of the box.
\item \texttt{getVolume}: returns the volume of the box.
\item \texttt{getSurfaceArea}: returns the total surface area of the box.
\ei

\item Additionally, the code as written does some error handling, but it is
lacking quite a bit of important error handling. Write some unit tests to
demonstrate as many cases of missing error handling as you can.

\ei

\subsection*{For The TAs (Students can ignore this section)}

Before the conclusion of the lab, please make sure that you have tested each
student to verify that they understand the basics of the lab exercise. For
students that understand the basics, please give them a grade of 1 for this Lab
Exercise.

\end{document}