1"use strict";(self.webpackChunkshaft_user_guide=self.webpackChunkshaft_user_guide||[]).push([["28971"],{76828(e,t,s){s.r(t),s.d(t,{metadata:()=>i,default:()=>h,frontMatter:()=>a,contentTitle:()=>l,toc:()=>o,assets:()=>d});var i=JSON.parse('{"id":"reference/guides/Testing_Pyramid","title":"The Testing Pyramid and Automation Strategy","description":"Understand the testing pyramid, the role of each testing level, and how to build an effective test automation strategy with SHAFT Engine.","source":"@site/docs/reference/guides/Testing_Pyramid.md","sourceDirName":"reference/guides","slug":"/reference/guides/Testing_Pyramid","permalink":"/docs/reference/guides/Testing_Pyramid","draft":false,"unlisted":false,"editUrl":"https://github.com/ShaftHQ/shafthq.github.io/blob/master/docs/reference/guides/Testing_Pyramid.md","tags":[{"inline":true,"label":"best-practices","permalink":"/docs/tags/best-practices"},{"inline":true,"label":"strategy","permalink":"/docs/tags/strategy"},{"inline":true,"label":"testing-pyramid","permalink":"/docs/tags/testing-pyramid"},{"inline":true,"label":"automation","permalink":"/docs/tags/automation"}],"version":"current","lastUpdatedAt":1790975565000,"frontMatter":{"id":"Testing_Pyramid","title":"The Testing Pyramid and Automation Strategy","sidebar_label":"Testing Pyramid","description":"Understand the testing pyramid, the role of each testing level, and how to build an effective test automation strategy with SHAFT Engine.","keywords":["SHAFT","testing pyramid","automation strategy","unit tests","integration tests","E2E tests","API tests","UI tests"],"tags":["best-practices","strategy","testing-pyramid","automation"]},"sidebar":"docs","previous":{"title":"Test Structure","permalink":"/docs/reference/guides/Test_Structure"},"next":{"title":"Tool Selection","permalink":"/docs/reference/guides/Tool_Selection"}}'),n=s(74848),r=s(28453);let a={id:"Testing_Pyramid",title:"The Testing Pyramid and Automation Strategy",sidebar_label:"Testing Pyramid",description:"Understand the testing pyramid, the role of each testing level, and how to build an effective test automation strategy with SHAFT Engine.",keywords:["SHAFT","testing pyramid","automation strategy","unit tests","integration tests","E2E tests","API tests","UI tests"],tags:["best-practices","strategy","testing-pyramid","automation"]},l,d={},o=[{value:"The Pyramid",id:"the-pyramid",level:2},{value:"Why the Pyramid Matters",id:"why-the-pyramid-matters",level:2},{value:"Unit Tests (Base)",id:"unit-tests-base",level:3},{value:"Integration / API Tests (Middle)",id:"integration--api-tests-middle",level:3},{value:"UI / E2E Tests (Top)",id:"ui--e2e-tests-top",level:3},{value:"Applying the Pyramid to Your Strategy",id:"applying-the-pyramid-to-your-strategy",level:2},{value:"Step 1: Identify What to Automate at Each Level",id:"step-1-identify-what-to-automate-at-each-level",level:3},{value:"Step 2: Maximize API Coverage",id:"step-2-maximize-api-coverage",level:3},{value:"Step 3: Reserve UI Tests for Critical Paths",id:"step-3-reserve-ui-tests-for-critical-paths",level:3},{value:"Where SHAFT Fits in the Pyramid",id:"where-shaft-fits-in-the-pyramid",level:2},{value:"Best Practices",id:"best-practices",level:2},{value:"Related",id:"related",level:2}];function c(e){let t={a:"a",admonition:"admonition",code:"code",div:"div",h2:"h2",h3:"h3",hr:"hr",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(t.p,{children:["The ",(0,n.jsx)(t.strong,{children:"testing pyramid"})," is a foundational concept in test automation strategy. It guides how many tests you should have at each level and where your automation investment delivers the most value."]}),"\n",(0,n.jsx)(t.hr,{}),"\n",(0,n.jsx)(t.h2,{id:"the-pyramid",children:"The Pyramid"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:" / UI / E2E \\ \u2190 Fewest, slowest, most expensive\n /\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\\\n / Integration/API \\ \u2190 Balanced count, moderate speed\n /\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\\\n / Unit Tests \\ \u2190 Most numerous, fastest, cheapest\n /\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\\\n"})}),"\n",(0,n.jsx)(t.div,{className:"table-scroll",role:"region",tabIndex:"0","aria-label":"The Pyramid",children:(0,n.jsxs)(t.table,{children:[(0,n.jsx)(t.thead,{children:(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.th,{children:"Level"}),(0,n.jsx)(t.th,{children:"Speed"}),(0,n.jsx)(t.th,{children:"Cost"}),(0,n.jsx)(t.th,{children:"Scope"}),(0,n.jsx)(t.th,{children:"Typical Count"})]})}),(0,n.jsxs)(t.tbody,{children:[(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:(0,n.jsx)(t.strong,{children:"Unit tests"})}),(0,n.jsx)(t.td,{children:"Very fast"}),(0,n.jsx)(t.td,{children:"Low"}),(0,n.jsx)(t.td,{children:"Single function or class"}),(0,n.jsx)(t.td,{children:"Thousands"})]}),(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:(0,n.jsx)(t.strong,{children:"Integration / API tests"})}),(0,n.jsx)(t.td,{children:"Fast"}),(0,n.jsx)(t.td,{children:"Moderate"}),(0,n.jsx)(t.td,{children:"Service interactions, API contracts"}),(0,n.jsx)(t.td,{children:"Hundreds"})]}),(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:(0,n.jsx)(t.strong,{children:"UI / E2E tests"})}),(0,n.jsx)(t.td,{children:"Slow"}),(0,n.jsx)(t.td,{children:"High"}),(0,n.jsx)(t.td,{children:"Full user flows through the UI"}),(0,n.jsx)(t.td,{children:"Tens to low hundreds"})]})]})]})}),"\n",(0,n.jsx)(t.hr,{}),"\n",(0,n.jsx)(t.h2,{id:"why-the-pyramid-matters",children:"Why the Pyramid Matters"}),"\n",(0,n.jsx)(t.p,{children:"Each level serves a different purpose:"}),"\n",(0,n.jsx)(t.h3,{id:"unit-tests-base",children:"Unit Tests (Base)"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"Test individual functions, methods, and classes in isolation."}),"\n",(0,n.jsx)(t.li,{children:"Run in milliseconds \u2014 fast feedback for developers."}),"\n",(0,n.jsx)(t.li,{children:"Catch logic errors early, before they propagate."}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Owned by developers"}),", run on every commit."]}),"\n"]}),"\n",(0,n.jsx)(t.h3,{id:"integration--api-tests-middle",children:"Integration / API Tests (Middle)"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"Test how components interact \u2014 API endpoints, database queries, service contracts."}),"\n",(0,n.jsx)(t.li,{children:"Faster and more stable than UI tests."}),"\n",(0,n.jsx)(t.li,{children:"Catch issues in data flow, serialization, authentication, and business rules."}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Where SHAFT's API testing shines"})," \u2014 use ",(0,n.jsx)(t.code,{children:"SHAFT.API"}
1)," to test REST endpoints efficiently."]}),"\n"]}),"\n",(0,n.jsx)(t.h3,{id:"ui--e2e-tests-top",children:"UI / E2E Tests (Top)"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"Test the complete user journey through the real application interface."}),"\n",(0,n.jsx)(t.li,{children:"Catch visual regressions, workflow issues, and integration gaps."}),"\n",(0,n.jsx)(t.li,{children:"Slowest and most brittle \u2014 use sparingly for critical paths."}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Where SHAFT's GUI testing shines"})," \u2014 use ",(0,n.jsx)(t.code,{children:"SHAFT.GUI.WebDriver"})," for web and mobile."]}),"\n"]}),"\n",(0,n.jsx)(t.admonition,{type:"warning",children:(0,n.jsxs)(t.p,{children:["An ",(0,n.jsx)(t.strong,{children:"inverted pyramid"})," (more UI tests than unit tests) is a common anti-pattern. It leads to slow test suites, flaky results, and high maintenance costs. Aim for the right balance."]})}),"\n",(0,n.jsx)(t.hr,{}),"\n",(0,n.jsx)(t.h2,{id:"applying-the-pyramid-to-your-strategy",children:"Applying the Pyramid to Your Strategy"}),"\n",(0,n.jsx)(t.h3,{id:"step-1-identify-what-to-automate-at-each-level",children:"Step 1: Identify What to Automate at Each Level"}),"\n",(0,n.jsx)(t.div,{className:"table-scroll",role:"region",tabIndex:"0","aria-label":"Step 1: Identify What to Automate at Each Level",children:(0,n.jsxs)(t.table,{children:[(0,n.jsx)(t.thead,{children:(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.th,{children:"Question"}),(0,n.jsx)(t.th,{children:"Level"})]})}),(0,n.jsxs)(t.tbody,{children:[(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:"Does this test validate a single calculation or transformation?"}),(0,n.jsx)(t.td,{children:(0,n.jsx)(t.strong,{children:"Unit"})})]}),(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:"Does this test verify an API contract, request/response, or service interaction?"}),(0,n.jsx)(t.td,{children:(0,n.jsx)(t.strong,{children:"API / Integration"})})]}),(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:"Does this test need a real browser or mobile device to verify a user workflow?"}),(0,n.jsx)(t.td,{children:(0,n.jsx)(t.strong,{children:"UI / E2E"})})]})]})]})}),"\n",(0,n.jsx)(t.h3,{id:"step-2-maximize-api-coverage",children:"Step 2: Maximize API Coverage"}),"\n",(0,n.jsxs)(t.p,{children:["API tests provide the best ",(0,n.jsx)(t.strong,{children:"cost-to-coverage ratio"}),". They are fast, stable, and cover the business logic that powers both the web and mobile UIs:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-java",metastring:'title="ApiTest.java"',children:'import com.shaft.driver.SHAFT;\nimport org.testng.annotations.Test;\n\npublic class ApiTest {\n private SHAFT.API api;\n\n @Test(description = "Verify user creation API")\n public void testCreateUser() {\n api = new SHAFT.API("https://api.example.com");\n api.post("/users")\n .setRequestBody("{\\"name\\": \\"John\\", \\"email\\": \\"[email protected]\\"}")\n .setContentType("application/json")\n ;\n api.assertThatResponse().extractedJsonValue("name").isEqualTo("John");\n api.assertThatResponse().extractedJsonValue("email").isEqualTo("[email protected]");\n api.verifyThatResponse().statusCode().isEqualTo(201);\n }\n}\n'})}),"\n",(0,n.jsx)(t.h3,{id:"step-3-reserve-ui-tests-for-critical-paths",children:"Step 3: Reserve UI Tests for Critical Paths"}),"\n",(0,n.jsx)(t.p,{children:"Use UI tests only for the most important user journeys \u2014 login, checkout, core workflows:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-java",metastring:'title="CriticalPathTest.java"',children:'import com.shaft.driver.SHAFT;\nimport org.openqa.selenium.By;\nimport org.testng.annotations.Test;\n\npublic class CriticalPathTest {\n private SHAFT.GUI.WebDriver driver;\n\n @Test(description = "Verify complete checkout flow")\n public void testCheckoutFlow() {\n driver = new SHAFT.GUI.WebDriver();\n driver.browser().navigateToURL("https://example.com");\n // Login \u2192 Browse \u2192 Add to cart \u2192 Checkout \u2192 Confirm\
1n // Only the most critical path needs a full UI test\n }\n}\n'})}),"\n",(0,n.jsx)(t.hr,{}),"\n",(0,n.jsx)(t.h2,{id:"where-shaft-fits-in-the-pyramid",children:"Where SHAFT Fits in the Pyramid"}),"\n",(0,n.jsxs)(t.p,{children:["SHAFT Engine supports ",(0,n.jsx)(t.strong,{children:"every level"})," of the pyramid above unit tests:"]}),"\n",(0,n.jsx)(t.div,{className:"table-scroll",role:"region",tabIndex:"0","aria-label":"Where SHAFT Fits in the Pyramid",children:(0,n.jsxs)(t.table,{children:[(0,n.jsx)(t.thead,{children:(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.th,{children:"Level"}),(0,n.jsx)(t.th,{children:"SHAFT Module"})]})}),(0,n.jsxs)(t.tbody,{children:[(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:"API / Integration"}),(0,n.jsxs)(t.td,{children:[(0,n.jsx)(t.code,{children:"SHAFT.API"})," \u2014 REST API testing"]})]}),(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:"CLI / Infrastructure"}),(0,n.jsxs)(t.td,{children:[(0,n.jsx)(t.code,{children:"SHAFT.CLI"})," \u2014 Terminal and file operations"]})]}),(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:"Database"}),(0,n.jsxs)(t.td,{children:[(0,n.jsx)(t.code,{children:"SHAFT.DB"})," \u2014 Database queries and validations"]})]}),(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:"UI / E2E (Web)"}),(0,n.jsxs)(t.td,{children:[(0,n.jsx)(t.code,{children:"SHAFT.GUI.WebDriver"})," \u2014 Browser automation"]})]}),(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:"UI / E2E (Mobile)"}),(0,n.jsxs)(t.td,{children:[(0,n.jsx)(t.code,{children:"SHAFT.GUI.WebDriver"})," \u2014 Appium-based mobile automation"]})]})]})]})}),"\n",(0,n.jsx)(t.admonition,{type:"info",children:(0,n.jsxs)(t.p,{children:["By using one engine across all levels, you get a ",(0,n.jsx)(t.strong,{children:"consistent API, unified reporting, and shared configuration"})," \u2014 regardless of what type of test you are writing."]})}),"\n",(0,n.jsx)(t.hr,{}),"\n",(0,n.jsx)(t.h2,{id:"best-practices",children:"Best Practices"}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Follow the pyramid shape"})," \u2014 more unit/API tests, fewer UI tests."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Automate API tests first"})," when building a new automation suite \u2014 highest ROI."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Use UI tests for critical paths only"})," \u2014 login, checkout, core business flows."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Push testing down"})," \u2014 if you can verify something with an API test, do not use a UI test."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Review your test distribution regularly"})," \u2014 measure how many tests exist at each level and rebalance."]}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"related",children:"Related"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"/docs/reference/guides/Solution_Design",children:"Solution Design"})}),"\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"/docs/reference/guides/Test_Structure",children:"Test Structure"})}),"\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"/docs/reference/guides/CI_CD_Integration",children:"Ci Cd Integration"})}),"\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"/docs/start/quick-start",children:"Quick Start"})}),"\n"]})]})}function h(e={}){let{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},28453(e,t,s){s.d(t,{R:()=>a,x:()=>l});var i=s(96540);let n={},r=i.createContext(n);function a(e){let t=i.useContext(r);return i.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:a(e.components),i.createElement(r.Provider,{value:t},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.