1"use strict";(self.webpackChunkpester_docs=self.webpackChunkpester_docs||[]).push([["1317"],{4283(e,t,n){n.r(t),n.d(t,{metadata:()=>s,default:()=>h,frontMatter:()=>d,contentTitle:()=>r,toc:()=>c,assets:()=>a});var s=JSON.parse('{"id":"usage/file-placement-and-naming","title":"File placement and naming","description":"Tips on how to name and structure your Pester test files and categorize your tests","source":"@site/versioned_docs/version-v5/usage/file-placement-and-naming.mdx","sourceDirName":"usage","slug":"/usage/file-placement-and-naming","permalink":"/docs/v5/usage/file-placement-and-naming","draft":false,"unlisted":false,"editUrl":"https://github.com/pester/docs/edit/main/versioned_docs/version-v5/usage/file-placement-and-naming.mdx","tags":[],"version":"v5","frontMatter":{"title":"File placement and naming","description":"Tips on how to name and structure your Pester test files and categorize your tests"},"sidebar":"docs","previous":{"title":"Installation","permalink":"/docs/v5/introduction/installation"},"next":{"title":"Importing tested functions","permalink":"/docs/v5/usage/importing-tested-functions"}}'),i=n(1987),o=n(7008);let d={title:"File placement and naming",description:"Tips on how to name and structure your Pester test files and categorize your tests"},r,a={},c=[{value:"Common convention",id:"common-convention",level:2},{value:"Hidden files and folders",id:"hidden-files-and-folders",level:2},{value:"Custom conventions",id:"custom-conventions",level:2},{value:"Categorizing tests",id:"categorizing-tests",level:2}];function l(e){let t={a:"a",admonition:"admonition",code:"code",em:"em",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h2,{id:"common-convention",children:"Common convention"}),"\n",(0,i.jsxs)(t.p,{children:["Pester considers all files named ",(0,i.jsx)(t.code,{children:".Tests.ps1"})," to be test files. This is the default naming convention that is used by almost all projects."]}),"\n",(0,i.jsxs)(t.p,{children:["Each file is called as the function it tests. This means that for a function ",(0,i.jsx)(t.code,{children:"Get-Emoji"})," we would have ",(0,i.jsx)(t.code,{children:"Get-Emoji.Tests.ps1"})," and ",(0,i.jsx)(t.code,{children:"Get-Emoji.ps1"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["Test files are placed in the same directory as the code that they test, or in a separate ",(0,i.jsx)(t.code,{children:"tests"})," directory that follows the same directory structure as the main src directory."]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:"Get-Emoji.ps1\nGet-Emoji.Tests.ps1\n\n# or\n\nsrc/public/Get-Emoji.ps1\ntests/public/Get-Emoji.Tests.ps1\n"})}),"\n",(0,i.jsx)(t.h2,{id:"hidden-files-and-folders",children:"Hidden files and folders"}),"\n",(0,i.jsxs)(t.p,{children:["On macOS and Linux a file or folder whose name starts with a dot \u2014 such as ",(0,i.jsx)(t.code,{children:".github"})," \u2014 is ",(0,i.jsx)(t.em,{children:"hidden"})," (on Windows the equivalent is the ",(0,i.jsx)(t.em,{children:"Hidden"})," file attribute). This matters when you mirror your source layout, because tests for code that lives in ",(0,i.jsx)(t.code,{children:".github"})," naturally end up in ",(0,i.jsx)(t.code,{children:"tests/.github"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["Pester follows the PowerShell default and ignores hidden items during discovery, so a recursive run over ",(0,i.jsx)(t.code,{children:"tests"})," silently skips anything under a hidden folder like ",(0,i.jsx)(t.code,{children:"tests/.github"}),"."]}),"\n",(0,i.jsxs)(t.admonition,{title:"Running tests inside a hidden folder",type:"note",children:[(0,i.jsxs)(t.p,{children:["Pass the hidden folder as an explicit path (",(0,i.jsx)(t.code,{children:"Invoke-Pester -Path ./tests/.github"}),") to include the non-hidden files inside it; test files that are themselves hidden must still be named explicitly."]}),(0,i.jsxs)(t.p,{children:["Pester v6 changes this default \u2014 it discovers hidden files and folders automatically, skipping only version-control directories (",(0,i.jsx)(t.code,{children:".git"}),", ",(0,i.jsx)(t.code,{children:".svn"})," and ",(0,i.jsx)(t.code,{children:".hg"}),")."]})]}),"\n",(0,i.jsx)(t.h2,{id:"custom-conventions",children:"Custom conventions"}),"\n",(0,i.jsxs)(t.p,{children:["The convention above is the default that most projects use, but Pester is not prescriptive about how you should name or place your files. The default extension can be customized by setting the ",(0,i.jsx)(t.code,{children:"Run.TestExtension"})," configuration option. The relative position of files can be then adjusted by changing the code you use to code files into tests. See ",(0,i.jsx)(t.a,{href:"importing-tested-functions",children:"Importing tested functions"}),"."]}),"\n",(0,i.jsx)(t.p,{children:"However the convention above is the default and is recommended to be used, especially when you are starting with Pester."}),"\n",(0,i.jsx)(t.h2,{id:"categorizing-tests",children:"Categorizing tests"}),"\n",(0,i.jsxs)(t.p,{children:["There can be many tests in one file, but in bigger projects you might want to distinguish, Unit, and Acceptance tests (or whatever are the categories of tests you have). This is typically approached by using tags. But another way is to split the tests in separate files and name them accordingly ",(0,i.jsx)(t.code,{children:"Get-Emoji.Unit.Tests.ps1"}),", ",(0,i.jsx)(t.code,{children:"Get-Emoji.Acceptance.Tests.ps1"}),". This keeps your Acceptance test and Unit test code separate, which might be a good idea as Acceptance tests are usually more complex, and require more dependencies."]}),"\n",(0,i.jsxs)(t.p,{children:["You can then use the ",(0,i.jsx)(t.code,{children:"Run.TestExtension"})," configuration option to customize the file extension convention to run only ",(0,i.jsx)(t.code,{children:"*.Unit.Tests.ps1"}),", only ",(0,i.jsx)(t.code,{children:"*.Acceptance.Tests.ps1"})," or keep the default to run all ",(0,i.jsx)(t.code,{children:"*.Tests.ps1"}),". Even more fine-grained control is possible by using the ",(0,i.jsx)(t.code,{children:"-ExcludePath"})," parameter, or by using ",(0,i.jsx)(t.code,{children:"Get-ChildItem"})," to filter all paths and then provide them to ",(0,i.jsx)(t.code,{children:"-Path"})," parameter."]})]})}function h(e={}){let{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},7008(e,t,n){n.d(t,{R:()=>d,x:()=>r});var s=n(1763);let i={},o=s.createContext(i);function d(e){let t=s.useContext(o);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:d(e.components),s.createElement(o.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.