Repository navigation
Expand file tree
/
Copy pathcomparison.html
More file actions
87 lines (87 loc) · 35.3 KB
/
Copy pathcomparison.html
File metadata and controls
87 lines (87 loc) · 35.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<!DOCTYPE html><html lang="en" dir="ltr" data-theme="dark" class="astro-g5ptsecz"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>API Test Base vs Postman, Bruno and Other API Clients - API Test Base</title><link rel="canonical" href="https://apitestbase.io/comparison"/><link rel="sitemap" href="/sitemap.xml"/><script async src="https://www.googletagmanager.com/gtag/js?id=G-728SGPGWQ6"></script><script>window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag('js',new Date());gtag('config','G-728SGPGWQ6');</script><link rel="apple-touch-icon" sizes="180x180" href="/favicons/apple-touch-icon.png"/><link rel="icon" type="image/png" sizes="16x16" href="/favicons/favicon-16x16.png"/><link rel="manifest" href="/favicons/site.webmanifest"/><link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#5bbad5"/><link rel="shortcut icon" href="/favicons/favicon-32x32.png" type="image/png"/><meta name="generator" content="Astro v7.3.5"/><meta name="generator" content="Starlight v0.42.4"/><meta property="og:title" content="API Test Base vs Postman, Bruno and Other API Clients"/><meta property="og:type" content="article"/><meta property="og:url" content="https://apitestbase.io/comparison"/><meta property="og:locale" content="en"/><meta property="og:description" content="API Test Base was built to verify what an API actually did, not only what it returned. Compare it with API clients, traffic replay tools and tests in code."/><meta property="og:site_name" content="API Test Base"/><meta name="twitter:card" content="summary_large_image"/><meta name="description" content="API Test Base was built to verify what an API actually did, not only what it returned. Compare it with API clients, traffic replay tools and tests in code."/><meta name="theme-color" content="#ffffff"/><script>
window.StarlightThemeProvider = (() => {
const storedTheme =
typeof localStorage !== 'undefined' && localStorage.getItem('starlight-theme');
const theme =
storedTheme ||
(window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark');
document.documentElement.dataset.theme = theme === 'light' ? 'light' : 'dark';
return {
updatePickers(theme = storedTheme || 'auto') {
document.querySelectorAll('starlight-theme-select').forEach((picker) => {
const select = picker.querySelector('select');
if (select) select.value = theme;
/** @type {HTMLTemplateElement | null} */
const tmpl = document.querySelector(`#theme-icons`);
const newIcon = tmpl && tmpl.content.querySelector('.' + theme);
if (newIcon) {
const oldIcon = picker.querySelector('svg.label-icon');
if (oldIcon) {
oldIcon.replaceChildren(...newIcon.cloneNode(true).childNodes);
}
}
});
},
};
})();
</script><template id="theme-icons"><svg aria-hidden="true" class="light astro-hkc32dio" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1em;"><path d="M5 12a1 1 0 0 0-1-1H3a1 1 0 0 0 0 2h1a1 1 0 0 0 1-1Zm.64 5-.71.71a1 1 0 0 0 0 1.41 1 1 0 0 0 1.41 0l.71-.71A1 1 0 0 0 5.64 17ZM12 5a1 1 0 0 0 1-1V3a1 1 0 0 0-2 0v1a1 1 0 0 0 1 1Zm5.66 2.34a1 1 0 0 0 .7-.29l.71-.71a1 1 0 1 0-1.41-1.41l-.66.71a1 1 0 0 0 0 1.41 1 1 0 0 0 .66.29Zm-12-.29a1 1 0 0 0 1.41 0 1 1 0 0 0 0-1.41l-.71-.71a1.004 1.004 0 1 0-1.43 1.41l.73.71ZM21 11h-1a1 1 0 0 0 0 2h1a1 1 0 0 0 0-2Zm-2.64 6A1 1 0 0 0 17 18.36l.71.71a1 1 0 0 0 1.41 0 1 1 0 0 0 0-1.41l-.76-.66ZM12 6.5a5.5 5.5 0 1 0 5.5 5.5A5.51 5.51 0 0 0 12 6.5Zm0 9a3.5 3.5 0 1 1 0-7 3.5 3.5 0 0 1 0 7Zm0 3.5a1 1 0 0 0-1 1v1a1 1 0 0 0 2 0v-1a1 1 0 0 0-1-1Z"/></svg><svg aria-hidden="true" class="dark astro-hkc32dio" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1em;"><path d="M21.64 13a1 1 0 0 0-1.05-.14 8.049 8.049 0 0 1-3.37.73 8.15 8.15 0 0 1-8.14-8.1 8.59 8.59 0 0 1 .25-2A1 1 0 0 0 8 2.36a10.14 10.14 0 1 0 14 11.69 1 1 0 0 0-.36-1.05Zm-9.5 6.69A8.14 8.14 0 0 1 7.08 5.22v.27a10.15 10.15 0 0 0 10.14 10.14 9.784 9.784 0 0 0 2.1-.22 8.11 8.11 0 0 1-7.18 4.32v-.04Z"/></svg><svg aria-hidden="true" class="auto astro-hkc32dio" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1em;"><path d="M21 14h-1V7a3 3 0 0 0-3-3H7a3 3 0 0 0-3 3v7H3a1 1 0 0 0-1 1v2a3 3 0 0 0 3 3h14a3 3 0 0 0 3-3v-2a1 1 0 0 0-1-1ZM6 7a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v7H6V7Zm14 10a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-1h16v1Z"/></svg></template><link rel="stylesheet" href="/_astro/print.ehPL0gv-.css" media="print"><link rel="stylesheet" href="/_astro/common.CKaRnBjS.css"><style>@layer starlight.components{svg:where(.astro-hkc32dio){color:var(--sl-icon-color);font-size:var(--sl-icon-size,1em);width:1em;height:1em}}
@layer starlight.components{starlight-tabs:where(.astro-scn3uvmv){display:block}.tablist-wrapper:where(.astro-scn3uvmv){overflow-x:auto}:where(.astro-scn3uvmv)[role=tablist]{border-bottom:2px solid var(--sl-color-gray-5);padding:0;list-style:none;display:flex}.tab:where(.astro-scn3uvmv){display:flex}.tab:where(.astro-scn3uvmv)>:where(.astro-scn3uvmv)[role=tab]{--sl-tab-color-border:var(--sl-color-gray-5);line-height:var(--sl-line-height-headings);box-shadow:0 2px 0 var(--sl-tab-color-border);color:var(--sl-color-gray-3);outline-offset:var(--sl-outline-offset-inside);overflow-wrap:initial;align-items:center;gap:.5rem;padding:.275rem 1.25rem;text-decoration:none;display:flex}.tab:where(.astro-scn3uvmv) :where(.astro-scn3uvmv)[role=tab][aria-selected=true]{--sl-tab-color-border:var(--sl-color-text-accent);color:var(--sl-color-white);font-weight:600}.tablist-wrapper:where(.astro-scn3uvmv)~[role=tabpanel]{margin-top:1rem}}
@layer starlight.components{.sl-link-button:where(.astro-dcqstdaq){font-size:var(--sl-text-sm);outline-offset:.25rem;border:1px solid #0000;border-radius:999rem;align-items:center;gap:.5em;padding:.4375rem 1.125rem;line-height:1.1875;text-decoration:none;display:inline-flex}.sl-link-button:where(.astro-dcqstdaq).primary{background:var(--sl-color-text-accent);border-color:var(--sl-color-text-accent);color:var(--sl-color-black)}.sl-link-button:where(.astro-dcqstdaq).primary:hover{color:var(--sl-color-black)}.sl-link-button:where(.astro-dcqstdaq).secondary{border-color:inherit;color:var(--sl-color-white)}.sl-link-button:where(.astro-dcqstdaq).minimal{color:var(--sl-color-white);padding-inline:0}.sl-link-button:where(.astro-dcqstdaq) svg{flex-shrink:0}@media (width>=50rem){.sl-link-button:where(.astro-dcqstdaq){font-size:var(--sl-text-base);padding:.9375rem 1.25rem}}.sl-markdown-content .sl-link-button:where(.astro-dcqstdaq){margin-inline-end:1rem}.sl-markdown-content .sl-link-button:where(.astro-dcqstdaq):not(:where(p *)){margin-block:1rem}}
</style><script type="module" src="/_astro/page.Dwipeu-R.js"></script></head><body class="astro-g5ptsecz"><a class="sl-skip-link astro-qb7clj6f" href="#_top">Skip to content</a><div class="page sl-flex astro-yntsjkba"><header class="header astro-yntsjkba"><div class="header astro-by6fddyj"><div class="title-wrapper sl-flex astro-by6fddyj"><a href="/" class="site-title sl-flex astro-6rvad3va"><span class="astro-6rvad3va" translate="no">API Test Base</span></a></div><div class="sl-flex print:hidden astro-by6fddyj"><site-search class="astro-by6fddyj astro-b5kgnn7o" data-translations="{"placeholder":"Search"}" data-strip-trailing-slash><button data-open-modal disabled aria-label="Search" aria-keyshortcuts="Control+K" class="astro-b5kgnn7o"><svg aria-hidden="true" class="astro-b5kgnn7o astro-hkc32dio" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1em;"><path d="M21.71 20.29 18 16.61A9 9 0 1 0 16.61 18l3.68 3.68a.999.999 0 0 0 1.42 0 1 1 0 0 0 0-1.39ZM11 18a7 7 0 1 1 0-14 7 7 0 0 1 0 14Z"/></svg><span class="sl-hidden md:sl-block astro-b5kgnn7o" aria-hidden="true">Search</span><kbd class="sl-hidden md:sl-flex astro-b5kgnn7o" style="display: none;"><kbd class="astro-b5kgnn7o">Ctrl</kbd><kbd class="astro-b5kgnn7o">K</kbd></kbd></button><dialog style="padding:0" aria-label="Search" class="astro-b5kgnn7o"><div class="dialog-frame sl-flex astro-b5kgnn7o"><button data-close-modal class="sl-flex md:sl-hidden astro-b5kgnn7o">Cancel</button><div class="search-container astro-b5kgnn7o"><div id="starlight__search" class="astro-b5kgnn7o"></div></div></div></dialog></site-search><script>
(() => {
const openBtn = document.querySelector('button[data-open-modal]');
const shortcut = openBtn?.querySelector('kbd');
if (!openBtn || !(shortcut instanceof HTMLElement)) return;
const platformKey = shortcut.querySelector('kbd');
if (platformKey && /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)) {
platformKey.textContent = '⌘';
openBtn.setAttribute('aria-keyshortcuts', 'Meta+K');
}
shortcut.style.display = '';
})();
</script><script type="module" src="/_astro/Search.astro_astro_type_script_index_0_lang.DZqJ8Bdf.js"></script></div><div class="sl-hidden md:sl-flex print:hidden right-group astro-by6fddyj"><div class="sl-flex social-icons astro-by6fddyj"><nav class="header-links always-visible astro-cj4t63pw"><a href="/docs/quick-start" class="astro-cj4t63pw">Docs</a><a href="/comparison" class="astro-cj4t63pw">Why API Test Base</a><a href="/feedback" class="astro-cj4t63pw">Feedback</a></nav></div><starlight-theme-select><label style="--sl-select-width: 6.25em" class="astro-2z5xp7gb"><span class="sr-only astro-2z5xp7gb">Select theme</span><svg aria-hidden="true" class="icon label-icon astro-2z5xp7gb astro-hkc32dio" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1em;"><path d="M21 14h-1V7a3 3 0 0 0-3-3H7a3 3 0 0 0-3 3v7H3a1 1 0 0 0-1 1v2a3 3 0 0 0 3 3h14a3 3 0 0 0 3-3v-2a1 1 0 0 0-1-1ZM6 7a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v7H6V7Zm14 10a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-1h16v1Z"/></svg><select autocomplete="off" class="astro-2z5xp7gb"><option value="dark" class="astro-2z5xp7gb">Dark</option><option value="light" class="astro-2z5xp7gb">Light</option><option value="auto" selected class="astro-2z5xp7gb">Auto</option></select><svg aria-hidden="true" class="icon caret astro-2z5xp7gb astro-hkc32dio" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1em;"><path d="M17 9.17a1 1 0 0 0-1.41 0L12 12.71 8.46 9.17a1 1 0 1 0-1.41 1.42l4.24 4.24a1.002 1.002 0 0 0 1.42 0L17 10.59a1.002 1.002 0 0 0 0-1.42Z"/></svg></label></starlight-theme-select><script>
StarlightThemeProvider.updatePickers();
</script><script type="module">var e=`starlight-theme`,t=e=>e===`auto`||e===`dark`||e===`light`?e:`auto`,n=()=>t(typeof localStorage<`u`&&localStorage.getItem(e));function r(t){typeof localStorage<`u`&&localStorage.setItem(e,t===`light`||t===`dark`?t:``)}var i=()=>matchMedia(`(prefers-color-scheme: light)`).matches?`light`:`dark`;function a(e){StarlightThemeProvider.updatePickers(e),document.documentElement.dataset.theme=e===`auto`?i():e,r(e)}matchMedia(`(prefers-color-scheme: light)`).addEventListener(`change`,()=>{n()===`auto`&&a(`auto`)});var o=class extends HTMLElement{constructor(){super(),a(n()),this.querySelector(`select`)?.addEventListener(`change`,e=>{e.currentTarget instanceof HTMLSelectElement&&a(t(e.currentTarget.value))})}};customElements.define(`starlight-theme-select`,o);</script><script type="module">var e=class extends HTMLElement{constructor(){super();let e=this.querySelector(`select`);e&&(e.addEventListener(`change`,e=>{e.currentTarget instanceof HTMLSelectElement&&(window.location.pathname=e.currentTarget.value)}),window.addEventListener(`pageshow`,t=>{if(!t.persisted)return;let n=e.querySelector(`option[selected]`)?.index;n!==e.selectedIndex&&(e.selectedIndex=n??0)}))}};customElements.define(`starlight-lang-select`,e);</script></div></div></header><div class="main-frame astro-yntsjkba"><script type="module">var e=document.getElementById(`starlight__sidebar`),t=e?.querySelector(`sl-sidebar-state-persist`),n=`sl-sidebar-state`,r=()=>{let r=[],i=t?.dataset.hash||``;try{let e=sessionStorage.getItem(n),t=JSON.parse(e||`{}`);Array.isArray(t.open)&&t.hash===i&&(r=t.open)}catch{}return{hash:i,open:r,scroll:e?.scrollTop||0}},i=e=>{try{sessionStorage.setItem(n,JSON.stringify(e))}catch{}},a=()=>i(r()),o=(e,t)=>{let n=r();n.open[t]=e,i(n)};t?.addEventListener(`click`,e=>{if(!(e.target instanceof Element))return;let t=e.target.closest(`summary`)?.closest(`details`);if(!t)return;let n=t.querySelector(`sl-sidebar-restore`),r=parseInt(n?.dataset.index||``);isNaN(r)||o(!t.open,r)}),addEventListener(`visibilitychange`,()=>{document.visibilityState===`hidden`&&a()});</script><div class="lg:sl-flex astro-lrzkfocr"><div class="main-pane astro-lrzkfocr"><main data-pagefind-body class="astro-g5ptsecz" lang="en" dir="ltr"><div class="content-panel astro-a7po4psb"><div class="sl-container astro-a7po4psb"><h1 id="_top" class="astro-bebwqqxs">API Test Base vs Postman, Bruno and Other API Clients</h1></div></div><div class="content-panel astro-a7po4psb"><div class="sl-container astro-a7po4psb"><starlight-image-zoom data-hide-caption class="astro-uhbei7rv"><template class="astro-uhbei7rv"><dialog class="starlight-image-zoom-dialog astro-uhbei7rv"><button aria-label="Unzoom image" class="starlight-image-zoom-control astro-uhbei7rv"><svg aria-hidden="true" fill="currentColor" viewBox="0 0 24 24" class="astro-uhbei7rv"><use href="#starlight-image-zoom-icon-unzoom" class="astro-uhbei7rv"></use></svg></button><figure class="astro-uhbei7rv"></figure></dialog></template><svg xmlns="http://www.w3.org/2000/svg" style="display:none" class="astro-uhbei7rv"><symbol id="starlight-image-zoom-icon-zoom" viewBox="0 0 24 24" class="astro-uhbei7rv"><path d="M9.79 12.79 4 18.59V17a1 1 0 0 0-2 0v4a1 1 0 0 0 .08.38 1 1 0 0 0 .54.54A1 1 0 0 0 3 22h4a1 1 0 0 0 0-2H5.41l5.8-5.79a1 1 0 0 0-1.42-1.42ZM21.92 2.62a1 1 0 0 0-.54-.54A1 1 0 0 0 21 2h-4a1 1 0 0 0 0 2h1.59l-5.8 5.79a1 1 0 0 0 0 1.42 1 1 0 0 0 1.42 0L20 5.41V7a1 1 0 0 0 2 0V3a1 1 0 0 0-.08-.38Z" class="astro-uhbei7rv"></path></symbol><symbol id="starlight-image-zoom-icon-unzoom" viewBox="0 0 24 24" class="astro-uhbei7rv"><path d="M21.71 2.29a1 1 0 0 0-1.42 0l-5.79 5.8V6.5a1 1 0 0 0-2 0v4a1 1 0 0 0 .08.38 1 1 0 0 0 .54.54 1 1 0 0 0 .38.08h4a1 1 0 0 0 0-2h-1.59l5.8-5.79a1 1 0 0 0 0-1.42ZM10.88 12.58a1 1 0 0 0-.38-.08h-4a1 1 0 0 0 0 2h1.59l-5.8 5.79a1 1 0 0 0 0 1.42 1 1 0 0 0 1.42 0l5.79-5.8v1.59a1 1 0 0 0 2 0v-4a1 1 0 0 0-.08-.38 1 1 0 0 0-.54-.54Z" class="astro-uhbei7rv"></path></symbol></svg></starlight-image-zoom><script type="module" src="/_astro/ImageZoom.astro_astro_type_script_index_0_lang.BMacvPKd.js"></script><div class="sl-markdown-content"><p>If you are evaluating API Test Base, chances are you already use an API client like Postman or Bruno. This page explains how API Test Base differs from these tools, and when it is the better fit. It also answers the question that usually comes next: why not write the tests in code?</p>
<div class="sl-heading-wrapper level-h2"><h2 id="an-api-client-but-that-is-not-why-it-exists">An API client, but that is not why it exists</h2><a class="sl-anchor-link" href="#an-api-client-but-that-is-not-why-it-exists"><span aria-hidden="true" class="sl-anchor-icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="m12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 1 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 0 0-1.42-1.42m8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 1 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 0 0 0 1.42 1 1 0 0 0 1.42 0l3.88-3.89a4.49 4.49 0 0 0 0-6.33M8.83 15.17a1 1 0 0 0 .71.29 1 1 0 0 0 .71-.29l4.92-4.92a1 1 0 1 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42"></path></svg></span><span class="sr-only" data-pagefind-ignore="">Section titled “An API client, but that is not why it exists”</span></a></div>
<p>When developers compare Postman with Bruno, they are mostly comparing how their work is stored and shared. Postman is a cloud-first platform built around accounts and workspaces. Bruno is open-source, offline-only and Git-native, created as a reaction against the cloud model. On the testing model the two agree: send a request, then assert on the response.</p>
<p>API Test Base does that job too, and it reaches protocols neither of them covers. Alongside HTTP and SOAP it sends and receives over JMS, IBM MQ and AMQP, moves files over FTP and SFTP, and runs scripts against a database. Browsing a queue or dropping a file on an SFTP server is an ordinary request here rather than a scripting job, and for some of these protocols you will struggle to find another general-purpose client at all.</p>
<p>But being an API client is not the reason API Test Base exists. Postman and Bruno already cover both halves of that work. With either of them you can send a request by hand, and you can run a saved collection as an automated suite, from the UI or from the command line in a pipeline. API Test Base was built for <strong><a href="/docs/what-is-integration-unit-testing">Integration Unit Testing</a></strong>: verifying what an API actually did, not only what it returned. That is the difference the rest of this page is about.</p>
<div class="sl-heading-wrapper level-h2"><h2 id="what-the-response-cannot-tell-you">What the response cannot tell you</h2><a class="sl-anchor-link" href="#what-the-response-cannot-tell-you"><span aria-hidden="true" class="sl-anchor-icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="m12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 1 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 0 0-1.42-1.42m8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 1 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 0 0 0 1.42 1 1 0 0 0 1.42 0l3.88-3.89a4.49 4.49 0 0 0 0-6.33M8.83 15.17a1 1 0 0 0 .71.29 1 1 0 0 0 .71-.29l4.92-4.92a1 1 0 1 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42"></path></svg></span><span class="sr-only" data-pagefind-ignore="">Section titled “What the response cannot tell you”</span></a></div>
<p>For a read-only API, the response is the only thing there is to verify: it is the whole of what the API produced. But an API that changes something does more than respond. Most often it writes to a database; it may also publish a message to a queue, or call a downstream service. Those <strong>side effects</strong> are frequently the API’s actual job, and the response says little or nothing about them. It usually carries an id and a status, not a report of what reached the database or the queue. A test that asserts on the response alone cannot tell you whether the shipment record was really created, or whether the event message really reached the queue.</p>
<p>API Test Base is built to verify both, in one test case:</p>
<div class="expressive-code"><link rel="stylesheet" href="/_astro/ec.w36nc.css"><script type="module" src="/_astro/ec.0vx5m.js"></script><figure class="frame not-content"><figcaption class="header"></figcaption><pre data-language="plaintext"><code><div class="ec-line"><div class="code"><span style="--0:#d6deeb;--1:#403f53">✓ HTTP response 201, with the new shipment id</span></div></div><div class="ec-line"><div class="code"><span style="--0:#d6deeb;--1:#403f53">✓ Row created in the SHIPMENTS table, status BOOKED</span></div></div><div class="ec-line"><div class="code"><span style="--0:#d6deeb;--1:#403f53">✓ Message published to the SHIPMENT.BOOKED queue</span></div></div><div class="ec-line"><div class="code"><span style="--0:#d6deeb;--1:#403f53">✓ Carrier API called with the weight and destination</span></div></div></code></pre><div class="copy"><div aria-live="polite"></div><button title="Copy to clipboard" data-copied="Copied!" data-code="✓ HTTP response 201, with the new shipment id✓ Row created in the SHIPMENTS table, status BOOKED✓ Message published to the SHIPMENT.BOOKED queue✓ Carrier API called with the weight and destination"><div></div></button></div></figure></div>
<p>The database check is a database test step with assertions on the query result; the queue check is a messaging test step that retrieves the message the API produced; the downstream call is verified through an <a href="/docs/http-stubs">HTTP stub</a> standing in for the real service. These steps are first-class citizens of the test case, created in the same no-code / low-code UI as the HTTP step.</p>
<p>In an API client, the same verification means standing up a helper HTTP API over the database, or maintaining custom scripts around the collection.</p>
<div class="sl-heading-wrapper level-h2"><h2 id="testing-apis-that-are-not-triggered-over-http">Testing APIs that are not triggered over HTTP</h2><a class="sl-anchor-link" href="#testing-apis-that-are-not-triggered-over-http"><span aria-hidden="true" class="sl-anchor-icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="m12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 1 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 0 0-1.42-1.42m8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 1 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 0 0 0 1.42 1 1 0 0 0 1.42 0l3.88-3.89a4.49 4.49 0 0 0 0-6.33M8.83 15.17a1 1 0 0 0 .71.29 1 1 0 0 0 .71-.29l4.92-4.92a1 1 0 1 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42"></path></svg></span><span class="sr-only" data-pagefind-ignore="">Section titled “Testing APIs that are not triggered over HTTP”</span></a></div>
<p>In integration and ESB landscapes, the “API” is often a message flow or service triggered by something other than an HTTP request:</p>
<ul>
<li>a message arriving on a queue — <a href="/docs/mq-request">IBM MQ</a>, <a href="/docs/jms-request">JMS</a>, <a href="/docs/amqp-request">AMQP</a>, or <a href="/docs/mqtt-request">MQTT</a></li>
<li>a file dropped on an <a href="/docs/ftp-request">FTP</a> or <a href="/docs/sftp-request">SFTP</a> server</li>
<li>a SOAP call</li>
</ul>
<p>API Test Base can send the trigger over the right protocol and then verify the outcome, so these APIs are tested the same way as REST APIs. API clients also reach beyond plain HTTP — Postman, for example, supports GraphQL, gRPC, WebSocket and MQTT — but their breadth targets modern web and IoT stacks. Enterprise messaging systems like IBM MQ, JMS and AMQP, file transfer over FTP and SFTP, and direct database access are covered by none of them.</p>
<div class="sl-heading-wrapper level-h2"><h2 id="test-setup-inside-the-test-case">Test setup inside the test case</h2><a class="sl-anchor-link" href="#test-setup-inside-the-test-case"><span aria-hidden="true" class="sl-anchor-icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="m12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 1 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 0 0-1.42-1.42m8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 1 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 0 0 0 1.42 1 1 0 0 0 1.42 0l3.88-3.89a4.49 4.49 0 0 0 0-6.33M8.83 15.17a1 1 0 0 0 .71.29 1 1 0 0 0 .71-.29l4.92-4.92a1 1 0 1 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42"></path></svg></span><span class="sr-only" data-pagefind-ignore="">Section titled “Test setup inside the test case”</span></a></div>
<p>Integration tests usually need data preparation: clear a table, insert a known record, then call the API and verify the change. In API Test Base these setup actions are ordinary test steps at the start of the test case, so every test is self-contained and starts from a known state. For larger suites, <a href="/docs/structured-test-setup-for-integration-unit-test-isolation">structured test setup</a> lets folders share setup steps without duplication.</p>
<p>This matters even for a read-only API, where the response really is the only thing to assert. Asserting the response of <code dir="auto">GET /shipments/123</code> only means something if the test put that shipment there first, and an API client can do that only by going through a helper API over the database.</p>
<p>Without setup, a read-only test has two ways out, and both cost something. It can assert less — a 200, a valid schema, a non-empty array — which survives whatever else is happening in a shared environment precisely because it checks so little. Or it can call the write API first and read back what it created, which is self-contained but fails whenever the write API is the thing that broke, and cannot produce states the write API has no way to create.</p>
<div class="sl-heading-wrapper level-h2"><h2 id="offline-first-no-account">Offline-first, no account</h2><a class="sl-anchor-link" href="#offline-first-no-account"><span aria-hidden="true" class="sl-anchor-icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="m12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 1 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 0 0-1.42-1.42m8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 1 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 0 0 0 1.42 1 1 0 0 0 1.42 0l3.88-3.89a4.49 4.49 0 0 0 0-6.33M8.83 15.17a1 1 0 0 0 .71.29 1 1 0 0 0 .71-.29l4.92-4.92a1 1 0 1 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42"></path></svg></span><span class="sr-only" data-pagefind-ignore="">Section titled “Offline-first, no account”</span></a></div>
<p>Here Bruno deserves credit: it made offline, no-account API tooling mainstream again. API Test Base takes the same stance — it is a free tool that you download and run on your own machine or in your <a href="/docs/integration-unit-testing-automation-in-cicd-pipeline">CI/CD pipeline</a>, with no account to create and no cloud the tool depends on. For teams working in restricted enterprise networks, this often matters as much as any feature. The difference between API Test Base and Bruno is not here — it is in everything above: what the tests can trigger, and what they can verify.</p>
<div class="sl-heading-wrapper level-h2"><h2 id="what-about-traffic-replay-tools">What about traffic replay tools?</h2><a class="sl-anchor-link" href="#what-about-traffic-replay-tools"><span aria-hidden="true" class="sl-anchor-icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="m12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 1 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 0 0-1.42-1.42m8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 1 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 0 0 0 1.42 1 1 0 0 0 1.42 0l3.88-3.89a4.49 4.49 0 0 0 0-6.33M8.83 15.17a1 1 0 0 0 .71.29 1 1 0 0 0 .71-.29l4.92-4.92a1 1 0 1 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42"></path></svg></span><span class="sr-only" data-pagefind-ignore="">Section titled “What about traffic replay tools?”</span></a></div>
<p>Another family of API testing tools — such as GoReplay and Keploy — works by capturing real traffic and replaying it later: the recorded requests are sent again, the API’s interactions with its dependencies are mocked from the recording, and the responses are compared against what was recorded. These tools answer a regression question: <em>does the API still behave like it did when the traffic was recorded?</em></p>
<p>API Test Base answers a different question: <em>does the API do what it is supposed to do?</em> Its tests are written from the API’s contract and verify real outcomes in real systems — after the API runs, the database really contains the new record and the output queue really holds the message. This also means the tests exist before there is any traffic to record, so a brand-new API can be tested from day one. This outcome-focused approach is the foundation of Integration Unit Testing, the method API Test Base is built around.</p>
<div class="sl-heading-wrapper level-h2"><h2 id="what-about-writing-the-tests-in-code">What about writing the tests in code?</h2><a class="sl-anchor-link" href="#what-about-writing-the-tests-in-code"><span aria-hidden="true" class="sl-anchor-icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="m12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 1 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 0 0-1.42-1.42m8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 1 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 0 0 0 1.42 1 1 0 0 0 1.42 0l3.88-3.89a4.49 4.49 0 0 0 0-6.33M8.83 15.17a1 1 0 0 0 .71.29 1 1 0 0 0 .71-.29l4.92-4.92a1 1 0 1 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42"></path></svg></span><span class="sr-only" data-pagefind-ignore="">Section titled “What about writing the tests in code?”</span></a></div>
<p>A developer writing code can verify anything. The test code starts the dependencies, sends the request, queries the table, reads the message off the queue, and checks what the API sent to the downstream service. It needs a test runner, a container library, a database client and an HTTP stubbing library such as WireMock. AI agents have made all of that much faster to produce.</p>
<p>So the question is not whether it can be done. It is what you are left holding afterwards, and what it costs to read.</p>
<p><strong>What it costs to read.</strong> An API Test Base test case has a fixed shape. The request, the database check and the check on the downstream call are steps in one place, and the dependency containers start from folder setup. You read named fields in the same arrangement every time, and the second test case reads like the first.</p>
<p>A code test is distributed by convention instead. The container fixture sits at class level so it can be shared, the stubs are built in the test, helper methods sit somewhere above, assertions are assembled from library calls, and parameterised data lives in annotations or a separate file. It is all one language, but nothing is in a fixed place.</p>
<p>Code is also free-form, which is usually a strength and here is a cost. Two developers writing the same test can produce two quite different files, and shared setup might sit in a setup method, a base class, or a static block. A reader cannot carry the shape of the last test into the next one.</p>
<p>This is not about a GUI being nicer to look at. It is that a labelled structure gives your question an address, where code has to be read in sequence before you know what it is doing. That difference matters more now that AI agents produce far more code than anyone used to review.</p>
<p><strong>What can be wrong in the test.</strong> Test code carries logic the author wrote: helpers, fixture wiring, assertions built up in steps. That logic can be wrong in ways that let the test pass while the API is broken. An API Test Base test step has no control flow of its own, so what remains to get right is the expected value, which is what a reviewer should be examining anyway. Your setup SQL and expressions are still yours to get right. The same difference shows up in review: a change to an expected value appears in the diff as a change to an expected value, where one edited helper can quietly alter a dozen assertions.</p>
<p><strong>Troubleshooting a failure.</strong> In API Test Base the test case is also the thing you poke the API with. You can invoke the API from the HTTP step on its own, read the response in the editor, adjust a value and re-run a single assertion. With code, the request exists twice — once in the test and once in the API client you explore with, such as Postman — so what you learn while poking has to be carried back by hand, and a failing test is re-run whole rather than one assertion at a time.</p>
<p><strong>Who else can read the test.</strong> This one arrives after adoption rather than on day one. Business analysts and architects do not read test suites, and there is no reason they should. But they do ask developers for a sample message, and they do need to know whether a design document still matches what the code actually does. Once the tests live in API Test Base, that lookup no longer has to go through a developer: the test case holds the message, and the run history says when it last passed, which is something no design document can tell them. Tests written in code cannot offer this, because reading them is developer work, so the knowledge stays inside the development team.</p>
<p><strong>Later, when the platform changes.</strong> Test cases written against an API’s contract know nothing about the language the API is written in, so they largely survive a change of API implementation language or platform. And a developer who moves between stacks does not have to hold a different testing framework in mind for each one, which has become a larger load now that AI agents generate test code in whichever framework they were pointed at.</p>
<div class="sl-heading-wrapper level-h2"><h2 id="where-api-test-base-fits">Where API Test Base fits</h2><a class="sl-anchor-link" href="#where-api-test-base-fits"><span aria-hidden="true" class="sl-anchor-icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="m12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 1 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 0 0-1.42-1.42m8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 1 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 0 0 0 1.42 1 1 0 0 0 1.42 0l3.88-3.89a4.49 4.49 0 0 0 0-6.33M8.83 15.17a1 1 0 0 0 .71.29 1 1 0 0 0 .71-.29l4.92-4.92a1 1 0 1 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42"></path></svg></span><span class="sr-only" data-pagefind-ignore="">Section titled “Where API Test Base fits”</span></a></div>
<p>For exploring HTTP APIs and running automated test suites, Postman and Bruno do the job well, and if one of them already suits you there is no need to switch. API Test Base will do that work too, and it is often the only option when the thing you need to send by hand goes to a queue, an SFTP server or a database.</p>
<p>What earns it a place in a project is the other question: not <em>“did the API respond correctly?”</em> but <em>“did the API actually do what it was supposed to do?”</em> Answering that means verifying the side effects, which is what <a href="/docs/what-is-integration-unit-testing">Integration Unit Testing</a> is for.</p>
<div class="sl-heading-wrapper level-h2"><h2 id="try-it">Try it</h2><a class="sl-anchor-link" href="#try-it"><span aria-hidden="true" class="sl-anchor-icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="m12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 1 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 0 0-1.42-1.42m8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 1 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 0 0 0 1.42 1 1 0 0 0 1.42 0l3.88-3.89a4.49 4.49 0 0 0 0-6.33M8.83 15.17a1 1 0 0 0 .71.29 1 1 0 0 0 .71-.29l4.92-4.92a1 1 0 1 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42"></path></svg></span><span class="sr-only" data-pagefind-ignore="">Section titled “Try it”</span></a></div>
<p>The <a href="/docs/quick-start">Quick Start</a> gets you from download to a running request in minutes, and <a href="/docs/creating-an-automated-test-case">Creating an Automated Test Case</a> shows a complete test that verifies a database side effect.</p></div><footer class="sl-flex astro-ddtxxk7k"><div class="meta sl-flex astro-ddtxxk7k"></div><div class="pagination-links print:hidden astro-b5raizh3" dir="ltr"></div></footer><div class="site-footer astro-jo6i4kqk"><p class="astro-jo6i4kqk">© API Test Base 2026</p></div></div></div></main></div></div></div></div></body></html>