R testthat

testthat tesmplate

# Test code goes here!
library(testthat)
# refer: http://r-pkgs.had.co.nz/tests.html
context(" ") # any info about this question
test_that("test sub question 1", {
  expect_equal(nchar("a"), 1)
  expect_true(var_name == correct_ans)
})
test_that("test sub question 2", {
  expect_equal(length("a"), 1)
})

A template for testing R code using testthat.

  1. Fill in some description in the context( or just ignore it).

  2. Test each sub questoins. For example you are asking student to calculate the (1)sum of 1 to 10, (2) sum of 11 to 20:

test_that("test sum of 1 to 10", {
  expect_equal(sum_10, 55)
})

test_that("test sum of 11 to 20", {
  expect_equal(sum_20, 165)
})

Hide answer

However if their submissions are wrong, expect_equal the error message will expose the correct answer.

sum_10 = 40
test_that("test sum of 1 to 10", {
  expect_equal(sum_10, 55)
})

Error: Test failed: ‘test sum of 1 to 10’ * sum_10 not equal to 55. 1/1 mismatches [1] 40 - 55 == -15

Message not equal to 55 indicate that the right answer is 55. It is better to use expect_true to hide the answer:

sum_10 = 40
correct_sum_10 = 55
test_that("test sum of 1 to 10", {
  expect_true(sum_10 == correct_sum_10)
})

Error: Test failed: ‘test sum of 1 to 10’ * sum_10 == correct_sum_10 isn’t true.

test functions

funs desc
expect_ture expression return true
expect_false expression return false
expect_equal(obj, expected, tolerance = 1e-5) modify tolerance to test float equal
expect_identical exactly the same
expect_length test length

For more test functions, refer to http://r-pkgs.had.co.nz/tests.html.

How to test a vector

# test x == c(1, 2,3)
x = 1:3
test_that('test x',{
  expect_equal(x, c(1,2,3))
})

answer = c(1,2,4)
test_that('test x',{
  expect_true(all(x == answer))
})

How to test a data.frame

df = head(iris)
# 1. class 
expect_is(df, 'data.frame') # if use dplyr, test if it is 
# 2. dimension
expect_equal(dim(df), c(6, 5))
# 3. colnames
answer = colnames(iris)
expect_equal(colnames(df), answer)
# 4. values
# It's hard to test all the values in a data.frame.
# one way is merge the data.frame with the coorrect and check 
# whether the dimension remains the same
answer = head(iris)
expect_equal(dim(merge(df, answer)), dim(df))

How to test ggplot2

## test a scatter plot in ggplot2
library(ggplot2)
p_scatterplot = ggplot(cars, aes(x=speed, y=dist)) + geom_point()

# 1. class 
expect_is(p_scatterplot, 'ggplot')
# 2. test mappings
expect_true(unlist(p_scatterplot)$mapping.x == 'speed')
expect_true(unlist(p_scatterplot)$mapping.y == 'dist')
# 3. test layer, whether it is a point layer
expect_is(layer_grob(p_scatterplot)[[1]], 'points')
# test labels and title
p_title = p_scatterplot + xlab('Speed (mpg)') + 
  ylab('Stopping Distance (ft)') + 
  ggtitle("Scatterplot of Speed/Distance")

# 1. x label
expect_true(unlist(p_title)$labels.x == 'Speed (mpg)')
# 2. y label
expect_true(unlist(p_title)$labels.y == 'Stopping Distance (ft)')
# 3. title
 expect_true(unlist(p_title)$labels.title == 'Scatterplot of Speed/Distance')

Python unittest

# Test code goes here!
import unittest
import json

class MyTest(unittest.TestCase):
    def setUp(self):
        pass # before all test* method run

    def tearDown(self):
        pass # after all test* method done

    # define testing functions here
    def test_sub_question_1(self):
        self.assertEqual(1, 1)
        self.assertAlmostEqual(1, 1-1e-14)

    def test_sub_question_2(self):
        self.assertEqual(1, 1)
        self.assertAlmostEqual(2, 9 / 4.5)

## dont touch the following code
if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(*[MyTest])
    testResult = unittest.TextTestRunner(verbosity=2).run(suite)
    total = testResult.testsRun
    if total == 0:
        res = {'score': 1, 'output': []}
    else:
        errors = [x[1] for x in testResult.errors]
        failures = [x[1] for x in testResult.failures]
        score = 1 - 1.0 * (len(errors) + len(failures)) / total
        res = {'score': score, 'test_output': errors + failures}
    print json.dumps(res)

Define methods inside the MyTest class, each sub question should have a correseponding test method. For example:

class MyTest(unittest.TestCase):
    # define testing functions here
    def test_sum10(self):
        self.assertEqual(sum_10, 55)
        
    def test_10devide3(self):
      # assertAlmostEqual used for float comparsion
      test_x =  10 / 3
      self.assertAlmostEqual(, 10 / 3.0)

test functions

funs desc
self.assertAlmostEqual test float numbers
self.assertTrue expression return true
self.assertFalse expression return false
self.assertIn in
self.assertNotIn not in
self.assertIsInstance if it belongs to a class
expect_identical exactly the same
expect_length test length

refer to https://docs.python.org/2/library/unittest.html.