Open In App

tinytest: Lightweight and Feature Complete Unit Testing Framework

Last Updated : 15 Jul, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

Unit Testing is an essential part of software development where we check whether the individual part of the code is running as intended. This helps in increasing the efficiency of the code. R is a statistical programming language that provides multiple such libraries and frameworks that are easy to use. This article will discuss one such unit testing framework in R called "tinytest".

What is tinytest?

tinytest is a lightweight, dependency-free unit testing framework for R Programming Language. It offers a straightforward way to write and run tests, making it a great choice for both small scripts and larger projects. It is simple and easy to use yet it offers many powerful tools to work with tinytest giving a simple approach to unit testing while covering all essential features. It supports.

  • Easy to write
  • Automatic discovery and execution of tests.
  • Comprehensive test result reporting.

Installation of tinytest

We can simply install this framework like any other package in R using install.packages().

# Install package
install.packages("tinytest")

# Load package
library(tinytest)

Implementation of tinytest

tinytest can be used for various reasons:

1. Testing Functions

One of the primary uses of tinytest is to test individual functions in R.

R
# Function to test
add <- function(x, y) {
  return(x + y)
}

# Test file: tests/test_add.R
library(tinytest)

# Basic arithmetic tests
expect_equal(add(1, 1), 2, info = "Adding 1 and 1 should equal 2")
expect_equal(add(-1, 1), 0, info = "Adding -1 and 1 should equal 0")
expect_equal(add(1.5, 2.5), 4, info = "Adding 1.5 and 2.5 should equal 4")

Output:

----- PASSED      : <-->
call| expect_equal(add(1, 1), 2, info = "Adding 1 and 1 should equal 2")
info| Adding 1 and 1 should equal 2

----- PASSED : <-->
call| expect_equal(add(-1, 1), 0, info = "Adding -1 and 1 should equal 0")
info| Adding -1 and 1 should equal 0

----- PASSED : <-->
call| expect_equal(add(1.5, 2.5), 4, info = "Adding 1.5 and 2.5 should equal 4")
info| Adding 1.5 and 2.5 should equal 4

2. Testing Statistical Models

This framework can also be used to test statistical model in R.

R
# Function to fit a linear model
fit_model <- function(data) {
  lm(y ~ x, data = data)
}

# Test file: tests/test_fit_model.R
library(tinytest)

# Sample data
data <- data.frame(x = 1:10, y = 2 * 1:10 + rnorm(10))

# Fit the model
model <- fit_model(data)

# Test that the model coefficients are approximately correct
expect_true(abs(coef(model)[2] - 2) < 0.5, info = "Slope should be approximately 2")

Output:

----- PASSED      : <-->
call| expect_true(abs(coef(model)[2] - 2) < 0.5, info = "Slope should be approximately 2")
info| Slope should be approximately 2

3. Testing Package Functions

This package can also test the other package function and whether they are working properly or not.

R
# Function to say hello in a package
hello <- function(name) {
  paste("Hello,", name)
}

# Test file: tests/test_hello.R
library(tinytest)

# Test the hello function
expect_equal(hello("Alice"), "Hello, Alice", 
             info = "Hello function should greet properly")

Output:

----- PASSED      : <-->
call| expect_equal(hello("Alice"), "Hello, Alice", info = "Hello function should greet properly")
info| Hello function should greet properly

4. Testing Error Handling

Ensuring that functions handle errors and edge cases properly is critical. tinytest can test that functions raise appropriate errors when given invalid inputs.

R
# Function with error handling
divide <- function(a, b) {
  if (b == 0) {
    stop("Division by zero")
  }
  return(a / b)
}

# Test file: tests/test_divide.R
library(tinytest)

# Test division
expect_equal(divide(6, 3), 2, info = "6 divided by 3 should equal 2")
expect_error(divide(1, 0), "Division by zero",
                          info = "Division by zero should raise an error")

Output:

----- PASSED      : <-->
call| expect_equal(divide(6, 3), 2, info = "6 divided by 3 should equal 2")
info| 6 divided by 3 should equal 2

----- PASSED : <-->
call| expect_error(divide(1, 0), "Division by zero", info = "Division by zero should raise an error")
info| Division by zero should raise an error

5. Testing Web Scraping and API Functions

When working with web scraping or APIs, it's important to test that the functions can handle various responses and edge cases correctly.

R
# Function to fetch data from an API
fetch_data <- function(url) {
  if (!grepl("^http", url)) {
    stop("Invalid URL")
  }
  # Simulate a successful fetch
  return(data.frame(id = 1, value = 42))
}

# Test file: tests/test_fetch_data.R
library(tinytest)

# Test fetching data
expect_error(fetch_data("invalid_url"), "Invalid URL", 
             info = "Invalid URL should raise an error")
expect_equal(fetch_data("http://example.com"), 
             data.frame(id = 1, value = 42), info = "Should fetch data correctly")

Output:

----- PASSED      : <-->
call| expect_error(fetch_data("invalid_url"), "Invalid URL", info = "Invalid URL should raise an error")
info| Invalid URL should raise
----- PASSED : <-->
call| expect_equal(fetch_data("http://example.com"), data.frame(id = 1,
call| value = 42), info = "Should fetch data correctly")
info| Should fetch data correctly

Best Practices

There are certain steps that should be taken in order to avoid issues in unit testing using tinytest:

  • Organize Tests: Test files must be kept organized in order to avoid any confusion.
  • Descriptive Info: Use the info parameter to provide descriptive messages. This helps understand the context of a test failure.
  • Test Coverage: Aim for high test coverage. Test all possible edge cases and error conditions.

Conclusion

This article explored the possible usage of tinytest package and framework with suitable examples. This gave a descriptive code for better understanding.


Next Article
Article Tags :

Similar Reads