1"use strict";(self.webpackChunkpester_docs=self.webpackChunkpester_docs||[]).push([["1667"],{7779(e,t,i){i.r(t),i.d(t,{metadata:()=>s,default:()=>h,frontMatter:()=>a,contentTitle:()=>o,toc:()=>d,assets:()=>l});var s=JSON.parse('{"id":"usage/testdrive","title":"Isolating File Operations using the TestDrive","description":"TestDrive is a PowerShell PSDrive where you can create temporary files used in your tests that are automatically cleaned up after your tests are finished","source":"@site/versioned_docs/version-v5/usage/testdrive.mdx","sourceDirName":"usage","slug":"/usage/testdrive","permalink":"/docs/v5/usage/testdrive","draft":false,"unlisted":false,"editUrl":"https://github.com/pester/docs/edit/main/versioned_docs/version-v5/usage/testdrive.mdx","tags":[],"version":"v5","frontMatter":{"id":"testdrive","title":"Isolating File Operations using the TestDrive","sidebar_label":"TestDrive","description":"TestDrive is a PowerShell PSDrive where you can create temporary files used in your tests that are automatically cleaned up after your tests are finished"},"sidebar":"docs","previous":{"title":"Modules","permalink":"/docs/v5/usage/modules"},"next":{"title":"TestRegistry","permalink":"/docs/v5/usage/testregistry"}}'),n=i(1987),r=i(7008);let a={id:"testdrive",title:"Isolating File Operations using the TestDrive",sidebar_label:"TestDrive",description:"TestDrive is a PowerShell PSDrive where you can create temporary files used in your tests that are automatically cleaned up after your tests are finished"},o,l={},d=[{value:"Scoping",id:"scoping",level:2},{value:"Example",id:"example",level:2},{value:"Compare with Literal Path",id:"compare-with-literal-path",level:2},{value:"Working with .NET Objects",id:"working-with-net-objects",level:2}];function c(e){let t={a:"a",admonition:"admonition",code:"code",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(t.p,{children:["TestDrive is a PowerShell PSDrive for file activity limited to the scope of a block (",(0,n.jsx)(t.a,{href:"../commands/Describe",children:"Describe"})," or ",(0,n.jsx)(t.a,{href:"../commands/Context",children:"Context"}),")."]}),"\n",(0,n.jsxs)(t.p,{children:["A test may need to work with file operations and validate certain types of file activities. It is usually desirable not to perform file activity tests that will produce side effects outside of an individual test. Pester creates a PSDrive inside the user's temporary drive that is accessible via a named PSDrive ",(0,n.jsx)(t.code,{children:"TestDrive:"}),". Pester will remove this drive after the tests completes. You may use this drive to isolate the file operations of your test to a temporary store."]}),"\n",(0,n.jsx)(t.h2,{id:"scoping",children:"Scoping"}),"\n",(0,n.jsx)(t.p,{children:"Basic scoping rules are implemented for the TestDrive:"}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsx)(t.li,{children:"A clean TestDrive is created per container (test-file or scriptblock) on entry to the first top-level block (Describe or Context) in that container."}),"\n",(0,n.jsx)(t.li,{children:"All files and folders created by your setups and tests are available during the lifetime of that block, including inner blocks."}),"\n",(0,n.jsx)(t.li,{children:"When exiting a block, files and folders created during it's lifetime will be removed. Modifications to items created in parent blocks are not reversed, see caution below."}),"\n",(0,n.jsx)(t.li,{children:"When the whole container is finished, the TestDrive and all files and folders inside it is deleted."}),"\n"]}),"\n",(0,n.jsx)(t.admonition,{title:"Modifications to existing items are not reversed",type:"warning",children:(0,n.jsx)(t.p,{children:"Be aware that the TestDrive content is tracked by paths. When entering a block, all paths which already exists will be excluded during cleanup when exiting the block.\nIn practice this means that if you create a file in the Describe block and then change its content inside the Context block, the modifications or deletions are preserved even after you left the Context block."})}),"\n",(0,n.jsx)(t.admonition,{title:"Using TestDrive in parallel runs",type:"note",children:(0,n.jsxs)(t.p,{children:["Internally the TestDrive creates a randomly named folder placed in $env",":Temp"," and links it to the TestDrive PSDrive.\nMaking the folder names random enables you to run multiple instances of Pester in parallel, as long as they are running as separate processes. That means running in different PowerShell.exe sessions or running using PowerShell jobs."]})}),"\n",(0,n.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-powershell",children:'BeforeAll {\n function Add-Footer($path, $footer) {\n Add-Content $path -Value $footer\n }\n}\n\nDescribe "Add-Footer" {\n BeforeAll {\n $testPath = "TestDrive:\\test.txt"\n Set-Content $testPath -value "my test text."\n Add-Footer $testPath "-Footer"\n $result = Get-Content $testPath\n }\n\n It "adds a footer" {\n (-join $result) | Should -Be "my test text.-Footer"\n }\n}\n'})}),"\n",(0,n.jsx)(t.h2,{id:"compare-with-literal-path",children:"Compare with Literal Path"}),"\n",(0,n.jsx)(t.p,{children:"Use the $TestDrive variable to compare regular paths with TestDrive paths. The following\ntwo paths will refer to the same file on disk, but the first one will c
1ontain the full file\nsystem path to the root of the TestDrive PSDrive, rather than a PowerShell path starting with\n'TestDrive:'."}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-powershell",children:"#eg. C:\\Users\\nohwnd\\AppData\\Local\\Temp\\264f1c74-464f-4387-b908-79e5eecba982\\somefile.txt\n$pathOne = Join-Path $TestDrive 'somefile.txt'\n\n$pathTwo = 'TestDrive:\\somefile.txt'\n"})}),"\n",(0,n.jsx)(t.p,{children:"To get the full path, you can use this snippet:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-powershell",children:"function GetFullPath {\n Param(\n [string] $Path\n )\n return $Path.Replace('TestDrive:', (Get-PSDrive TestDrive).Root)\n}\n"})}),"\n",(0,n.jsx)(t.h2,{id:"working-with-net-objects",children:"Working with .NET Objects"}),"\n",(0,n.jsxs)(t.p,{children:["When working directly with .NET objects, it's not possible to use the convenient ",(0,n.jsx)(t.code,{children:"TestDrive:\\"})," PSDrive. Instead you need to use the ",(0,n.jsx)(t.code,{children:"$TestDrive"})," variable which holds the actual path in a format that .NET understands. For example instead of using ",(0,n.jsx)(t.code,{children:"TestDrive:\\somefile.txt"})," use ",(0,n.jsx)(t.code,{children:"$TestDrive\\somefile.txt"})," instead."]})]})}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)}},7008(e,t,i){i.d(t,{R:()=>a,x:()=>o});var s=i(1763);let n={},r=s.createContext(n);function a(e){let t=s.useContext(r);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:a(e.components),s.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.