Skip to content

Instructions

Bash Logo

Hey, you made it through the setup, congratulations!

You are now ready for the actual workshop.

Workshop Files

Before you begin, it is important that you know how the lab files you will be working with are laid out.

Inside the repository that you pulled down via a git clone during the workshop setup, you should notice a labs/ directory. This contains all the files you will be editing for the workshop. Each lab within the workshop has its own sub-directory and three files inside. Go ahead and navigate to there and check out what is inside.

cd labs/ \
&& ls ./

You should notice a series of sub-directories, each containing the same types of files.

For example, here are the files for the "variables" lab in the "variables/" sub-directory.

variables.lab.sh  variables.solution.sh  variables.test.sh

Lab Files

The files ending in .lab.sh are the files you will be editing. These files are incomplete.

Each lab file will contain a set of instructions in the form of code comments. Code comments in bash are pre-faced with the "#" character, and can occur either by themselves on a line, or after a valid line of code that has been terminated. For example:

# This is a valid code comment
my_command

my_command   # This is also a valid comment

Watch for instructions in both types of locations. Here is an example comment.

sobash_example_lab() {

  number=5

  # Replace the value of the "number" variable with a number that makes the statement below true
  if [[ "2" == "$number" ]]; then
    echo "this statement is true."
  else
    echo "this statement is false."
  fi

}

Based on these instructions, you would update the file to look like this:

sobash_example_lab() {

  number=2

  # Replace the value of the "number" variable with a number that makes the statement below true
  if [[ "2" == "$number" ]]; then
    echo "this statement is true."
  else
    echo "this statement is false."
  fi

}

Updating the line number=5 to read number=2 would make the program (once executed) print

"this statement is true."

to the terminal, per the instructions.

Solution Files

The files ending in .solution.sh contain an example of a complete lab file that passes all the lab's test cases.

This file can be used as you work through the labs to show you an example of one way to complete a lab. However, this is rarely the only way to complete a lab. Any lab that passes the tests defined in the test files (discussed next) is considered technically correct.

For example, looking back at our previous example lab, here is another answer to that lab that would still result in a passing test, assuming the test case was just checking for "this statement is true." to be printed to the terminal.

sobash_example_lab() {

  number="$((5-3))"

  # Replace the value of the "number" variable with a number that makes the statement below true
  if [[ "2" == "$number" ]]; then
    echo "this statement is true."
  else
    echo "this statement is false."
  fi

}

This answer may not be the simplest to write, easiest to read, or the fastest to execute, but it is "right" according to the test case for this example lab.

Test Files

The files ending in .test.sh contain test cases for the test framework to use to test your lab file.

These test files are written using a test framework called shunit2, a copy of which is included directly in this repository.

The shunit2 utility is written and maintained by Kate Ward.

It provides developers of code written in Bash (and other shell languages) with a handy set of functions that can be used to test their individual functions in isolation (unit testing), or several functions at once (integration testing).

More information about how to write tests using this great framework can be found in the shunit2 repository.

The test cases for all of the labs can be executed by running the test wrapper script located in the "src/" sub-directory within the "bash-programming" repository. This wrapper script will build either all the .lab.sh files or all of the .solution.sh files into a single program file, and then execute that resulting program to test the functionality of either one specific or all of the functions defined in the workshop files.

To use the test wrapper script, simply run the following:

cd "${HOME}/bash-programming/src/" \
&& ./test.sh solution example

This example command tests the "solution" file for the "example" lab. The output should look something like this:

[INFO] build_main | Starting build process.

[INFO] build_main | Adding code from file (../labs/00-example/00-example.solution.sh) to program (../build/sobash).

...   # Output abbreviated

[INFO] test_main | Executing test file (../labs/00-example/00-example.test.sh).
test_statement_is_true

Ran 1 test.

OK

Once you think you have completed the "example" lab, you can replace the string "solution" with "lab" to check your work, like so:

cd "${HOME}/bash-programming/src/" \
&& ./test.sh lab example

If you did not find a passing solution, the output should look something like this:

[INFO] build_main | Starting build process.

[INFO] build_main | Adding code from file (../labs/00-example/00-example.lab.sh) to program (../build/sobash).

...   # Output abbreviated

[INFO] test_main | Executing test file (../labs/00-example/00-example.test.sh).
test_statement_is_true
ASSERT:expected:<this statement is true.> but was:<this statement is false.>
shunit2:ERROR test_statement_is_true() returned non-zero return code.

Ran 1 test.

Here is what the test file might look like for that example lab.

test_statement_is_true() {
  output="$(../build/sobash example-lab)"
  assertEquals "this statement is true." "$output"
}

source ./shunit2

This test first runs the example lab function and saves the output as the value of the "output" variable. It then compares the value of that variable to the literal string "this statement is true." to see if it matches. The "assertEquals" function comes from shunit2, and if the two inputs are the same (the string and the output variable), the test framework will mark this as a passing test. If the two inputs are not the same, it will mark this as a failing test.