% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/docs.R
\name{introduction}
\alias{introduction}
\title{Happy HTTP testing with webfakes}
\description{
Happy HTTP testing with webfakes
}
\section{Happy HTTP testing with webfakes}{

\subsection{What is webfakes?}{

Webfakes is an R package that can spin up web servers on your machine to facilitate testing R code.
R code that needs an HTTP connection is not trivial to test:
\itemize{
\item Connectivity problems might prevent the tests from accessing the web server.
\item The web server might need authentication, and it is not easy to convey login information to the test suite in a secure way.
\item The web server might have rate limits, i.e, it limits the number of queries per hour or day, causing some spurious test failures.
\item You might want to test in non-normal conditions, e.g. with low bandwidth, or when the client is rate limited. These conditions don't normally happen on the web server and they are hard to trigger.
}

With webfakes you can easily start a custom web app, that is running on the local machine.
\itemize{
\item Webfakes does not need a network connection.
\item Webfakes does not need authentication. Well, unless you want it to.
\item Webfakes does not have rate limits.
\item Webfakes can simulate low bandwidth, or a broken connection.
}
}

\subsection{Webfakes vs mocking}{

Mocking is a general technique to mimic the behavior of a function or object that is needed in test case.
In the case of HTTP requests, this typically means that both the request and its response are recorded when the tests run the first time, and saved to disk.
Subsequent test runs intercept the HTTP requests, match them against the recorded requests and then replay the corresponding recorded response.
See for example the \href{https://docs.ropensci.org/vcr/}{vcr} and \href{https://enpiar.com/r/httptest/}{httptest} R packages.

The advantages of using your own webfakes server, over mocking:
\itemize{
\item Simpler infrastructure. No separate recording and replaying phases, no recorded files. No request matching.
\item You can use any web client you want. E.g. curl and base R's HTTP functions do not explicitly support mocking currently.
\item No need to worry about sensitive information in recorded requests or responses.
\item Often easier to use when testing non-normal conditions, e.g. errors that are hard to trigger, low bandwidth, or rate limits.
\item Works if you stream data from a HTTP connection, instead of reading the whole response at once.
\item You can reuse the same app for multiple tests, in multiple packages.
\item Easier to use for tests that require multiple rounds of requests.
\item Comes with a built-in \verb{https://httpbin.org} compatible app, chances are, you don't even need to write your testing app, just start writing tests right away.
\item Better test writing experience. This is subjective, and your mileage may vary.
}
}

\subsection{Webfakes vs the real API}{
\itemize{
\item No network needed. No more \code{skip_if_offline()}.
\item Much faster.
\item No rate limits. But you can simulate one if you want to.
\item You can write your custom app.
\item Simulate low bandwidth or a broken connection.
}
}

\subsection{Webfakes vs httpbin.org}{
\itemize{
\item No network needed. No more \code{skip_if_offline()}.
\item Much faster.
\item You can use the built-in \code{webfakes::httpbin_app()} app, so it is easy to switch from httpbin.org.
\item You can write your custom app, httpbin.org might not have what you need.
}
}

\subsection{Using \code{webfakes::httpbin_app()} with testthat}{

You can use testthat's setup files. You start the app in a setup file and also register a teardown expression for it. \code{local_app_process()} can do both in one go. Your \code{tests/testthat/setup-http.R} may look like this:

\if{html}{\out{<div class="sourceCode r">}}\preformatted{http <- webfakes::local_app_process(
  webfakes::httpbin_app(),
  .local_envir = testthat::teardown_env()
)
}\if{html}{\out{</div>}}

(Before testthat 3.0.0, you had to write the teardown expression in a \code{tests/testthat/teardown-http.R} file. That still works, but a single setup file is considered to be better practice, see \href{https://testthat.r-lib.org/articles/test-fixtures.html}{this testthat vignette}.)

In the test cases you can query the \code{http} app process to get the URLs you need to connect to:

\if{html}{\out{<div class="sourceCode r">}}\preformatted{test_that("fails on 404", \{
  url <- http$url("/status/404")
  response <- httr::GET(url)
  expect_error(
    httr::stop_for_status(response),
    class = "http_404"
  )
\})
#> Test passed
}\if{html}{\out{</div>}}

When writing your tests interactively, you may create a \code{http} app process in the global environment, for convenience. You can \code{source()} your \code{setup-http.R} file for this. Alternatively, you can start the app process in a helper file. See "How do I start the app when writing the tests?" just below.

You can also create a web server for a test file, or even for a single test case.
See \code{vignette("how-to")} for details how.
}

\subsection{Writing apps}{

If the builtin \code{httpbin_app()} is not appropriate for your tests, you can write your own app.
You can also extend the \code{httpbin_app()} app, if you don't want to start from scratch.

You create a new app with \code{new_app()}.
This returns an object with methods to add middleware and API
endpoints to it.
For example, a simple app that returns the current time in JSON would
look like this:

\if{html}{\out{<div class="sourceCode r">}}\preformatted{time <- webfakes::new_app()
time$get("/time", function(req, res) \{
  res$send_json(list(time = format(Sys.time())), auto_unbox = TRUE)
\})
}\if{html}{\out{</div>}}

Now you can start this app on a random port using \code{web$listen()}.
Alternatively, you can start it in a subprocess with \code{new_app_process()}.

\if{html}{\out{<div class="sourceCode r">}}\preformatted{web <- webfakes::new_app_process(time)
web$url()
#> [1] "http://127.0.0.1:64358/"
}\if{html}{\out{</div>}}

Use \code{web$url()} to query the URL of the app. For example:

\if{html}{\out{<div class="sourceCode r">}}\preformatted{url <- web$url("/time")
httr::content(httr::GET(url))
#> $time
#> [1] "2025-01-14 10:07:33"
}\if{html}{\out{</div>}}

\code{web$stop()} stops the app and the subprocess as well:

\if{html}{\out{<div class="sourceCode r">}}\preformatted{web$stop()
web$get_state()
#> [1] "not running"
}\if{html}{\out{</div>}}

\code{local_app_process()} is similar to \code{new_app_process()}, but it stops the server process at the end of the calling block.
This means that the process is automatically cleaned up at the end of a \code{test_that()} block or at the end of the test file.

You can create your app at the beginning of your test file.
Or, if you want to use the same app in multiple test files, use a
\href{https://testthat.r-lib.org/reference/test_file.html#special-files}{testthat helper file}.
Sometimes it useful if your users can create and use your test app,
for example to create reproducible examples.
You can include a (possibly internal) function in your package, that
creates the app.

See \code{?new_app()}, \code{?new_app_process()} and \code{?local_app_process} for more details.
}
}

