{"id":82495,"date":"2017-10-03T09:00:05","date_gmt":"2017-10-03T16:00:05","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/?p=82495"},"modified":"2019-02-18T09:10:09","modified_gmt":"2019-02-18T16:10:09","slug":"use-docker-to-automate-testing-of-powershell-core-scripts","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/use-docker-to-automate-testing-of-powershell-core-scripts\/","title":{"rendered":"Use Docker to automate testing of PowerShell Core scripts"},"content":{"rendered":"<p>&nbsp;<\/p>\n<p><strong>Summary:<\/strong> Learn the basics about Docker, and see how to use it for PowerShell Core script testing on different operating systems.<\/p>\n<p>I&#8217;m Dan Ward, a Boston-based .NET software engineer who is just plum crazy about PowerShell and automation. Earlier this year, I uploaded my first GitHub project\u2014a <a target=\"_blank\" href=\"https:\/\/github.com\/DTW-DanWard\/PowerShell-Beautifier\" rel=\"noopener noreferrer\">PowerShell whitespace cleaner<\/a> that also replaces aliases with commands and fixes casing issues. Like any manager of a new project, I was excited to see people using it and providing feedback and enhancement requests. But I became concerned when bug reports started coming in: &#8220;But I tested this on my machine before uploading, like, a thousand times!&#8221;\u009d (How often have you said that?)<\/p>\n<h2>PowerShell Core<\/h2>\n<p>Turns out I was testing in Windows PowerShell on a Windows machine, and the users having issues were using PowerShell Core that was running natively on <em>non-Windows machines<\/em>. Yes, the next generation of PowerShell is open source, and runs on Windows, Macs, and many Linux distributions. If you haven&#8217;t <a target=\"_blank\" href=\"https:\/\/devblogs.microsoft.com\/powershell\/powershell-6-0-roadmap-coreclr-backwards-compatibility-and-more\/\" rel=\"noopener noreferrer\">read up on PowerShell Core<\/a> yet, <a target=\"_blank\" href=\"https:\/\/blogs.msdn.microsoft.com\/powershell\/2017\/06\/09\/getting-started-with-powershell-core-on-windows-mac-and-linux\/\" rel=\"noopener noreferrer\">you should<\/a>\u2014or even better, <a target=\"_blank\" href=\"https:\/\/github.com\/PowerShell\/PowerShell#get-powershell\" rel=\"noopener noreferrer\">download it<\/a> and try it out now.<\/p>\n<p>For most scripting activities, Windows PowerShell and PowerShell Core are very similar\u2014but there are still some differences. And because PowerShell Core now runs across different operating systems, you need to start testing across these operating systems if you want to find any unexpected incompatibilities before your clients do.<\/p>\n<p>But, like you, I really don&#8217;t want to buy a lot of new hardware to test my work on different operating systems. And setting up VMs for all these operating systems is time consuming.<\/p>\n<h2>Docker to the Rescue!<\/h2>\n<p><a target=\"_blank\" href=\"https:\/\/www.docker.com\/\" rel=\"noopener noreferrer\">Docker<\/a> is an awesome containerization technology, and if somehow you haven&#8217;t read about it <a target=\"_blank\" href=\"https:\/\/www.docker.com\/what-docker\" rel=\"noopener noreferrer\">you need to<\/a> <a target=\"_blank\" href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/standard\/microservices-architecture\/container-docker-introduction\/index\" rel=\"noopener noreferrer\">right now<\/a>. One of the many benefits of using containers is that you can easily package up software to share with others. And the PowerShell Core team is doing just that: whenever they put out a new version, they provide packages for native installation and <a target=\"_blank\" href=\"https:\/\/hub.docker.com\/r\/microsoft\/powershell\/tags\/\" rel=\"noopener noreferrer\">Docker images with PowerShell Core<\/a> for popular operating systems. Want to test the latest version of PowerShell Core on Ubuntu? Just pull that image and start it up. In fact, let&#8217;s do that right now.<\/p>\n<h2>Docker walkthrough with PowerShell Core images<\/h2>\n<p>Note: this walkthrough uses <a target=\"_blank\" href=\"https:\/\/www.docker.com\/docker-windows\" rel=\"noopener noreferrer\">Docker for Windows<\/a> on a Windows 10 Pro machine. If you have an older Windows operating system, you would need to use Docker Toolbox, which may not work out of the box in PowerShell.<\/p>\n<p>If you want to follow along on your own machine, install Docker for Windows before continuing, and download the PowerShell whitespace cleaner.<\/p>\n<p>First, in a browser, let&#8217;s check out the <a target=\"_blank\" href=\"https:\/\/hub.docker.com\/r\/microsoft\/powershell\/tags\/\" rel=\"noopener noreferrer\">Microsoft PowerShell Core Docker image repository<\/a>.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/01-docker-testing-09272017.png\"><img decoding=\"async\" width=\"517\" height=\"620\" class=\"alignnone size-full wp-image-82505\" alt=\"Screenshot of image repository\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/01-docker-testing-09272017.png\" \/><\/a><\/p>\n<p>There are several things to note here:<\/p>\n<ul>\n<li>This page is served from Docker Hub. Docker Hub is a public registry; a place where anyone can create a repository and can upload or download container images.<\/li>\n<li>This Docker Hub repository name is: <strong>microsoft\/powershell<\/strong>. Repository names are [team or person name]\/[project name].<\/li>\n<li>A tag is a label that helps identify a unique image. In the PowerShell Core repository, you can see they are using tags to identify not just different operating systems, but versions of the operating systems.<\/li>\n<li>When working with images, you identify them with [repository name]:[tag name]. However, :[tag name] is optional. If tag name is not specified, Docker uses the <strong>latest <\/strong>tag. In looking at the microsoft\/powershell repository, <strong>latest<\/strong> looks like a reference to ubuntu16.04 (same size).<\/li>\n<\/ul>\n<p>Great! So how do I know what images I have installed locally, and how do I pull an image to my machine?<\/p>\n<h2>Listing and pulling images<\/h2>\n<p>To list images on your local machine, use the docker images command.<\/p>\n<p style=\"padding-left: 60px\"><code>PS C:\\&gt; docker images\n<\/code><\/p>\n<p style=\"padding-left: 60px\"><code>REPOSITORY \u00a0 \u00a0 TAG \u00a0 \u00a0 IMAGE ID \u00a0 \u00a0 CREATED \u00a0 \u00a0 SIZE\n<\/code><\/p>\n<p style=\"padding-left: 60px\"><code>PS C:\\&gt; # no images<\/code><\/p>\n<p>Let&#8217;s pull down a PowerShell Core image for a popular Linux distribution named Ubuntu; we&#8217;ll use the 16.04 version.<\/p>\n<p style=\"padding-left: 60px\"><code>\nPS C:\\&gt; docker pull microsoft\/powershell:ubuntu16.04\nubuntu16.04: Pulling from microsoft\/powershell\nd5c6f90da05d: Pull complete\nbbbe761fcb56: Pull complete\n7afa5ede606f: Pull complete\nf6b7253b56f4: Pull complete\n2b8db33536d4: Pull complete\n34ce21a172dd: Pull complete\ndb4e21036b1a: Pull complete\na553072824c6: Pull complete\ncc09983fea92: Pull complete\n3464f05d5785: Pull complete\nDigest: sha256:c91708f5ba6f3b55da158eac0380f3c2bb907039d547b7ae52564dd7a0a3af8a\nStatus: Downloaded newer image for microsoft\/powershell:ubuntu16.04\nPS C:\\&gt; # let\u2019s make sure we see that image\nPS C:\\&gt; docker images\nREPOSITORY \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 TAG \u00a0 \u00a0 \u00a0 \u00a0 IMAGE ID \u00a0 \u00a0 CREATED \u00a0 \u00a0\u00a0 SIZE\nmicrosoft\/powershell ubuntu16.04 bbbb17a9d348 11 hours ago 381MB\nPS C:\\&gt;\n<\/code><\/p>\n<p>As you can see, the first run of docker images had no results. After pulling microsoft\/powershell:ubuntu16.04, we now have one image on the machine.<\/p>\n<h2>Creating, starting, and connecting to a container<\/h2>\n<p>Now that we have the image, we can create a container, and start it up in one step, with the docker run command.<\/p>\n<p style=\"padding-left: 60px\"><code>\nPS C:\\&gt; # this is a normal Windows PowerShell\nPS C:\\&gt; docker run -i -t microsoft\/powershell:ubuntu16.04 powershell\nPowerShell v6.0.0-beta.7\nCopyright (C) Microsoft Corporation. All rights reserved.\nPS \/&gt; # pretty sure I\u2019m in PowerShell... but that PS \/&gt; prompt looks different\n<\/code><\/p>\n<p>Hold on, how can I be sure I&#8217;m in a PowerShell session in a Linux container?<\/p>\n<p style=\"padding-left: 60px\"><code>\nPS \/&gt; dir\nDirectory: \/\nMode \u00a0 LastWriteTime \u00a0 Length Name\n---- \u00a0 ------------- \u00a0 ------ ----\nd----- 8\/2\/17 2:10 PM \u00a0 \u00a0 \u00a0 \u00a0 bin\nd----- 4\/12\/16 8:14 PM \u00a0 \u00a0 \u00a0\u00a0 boot\nd----- 9\/17\/17 7:09 PM \u00a0 \u00a0 \u00a0\u00a0 dev\nd----- 9\/17\/17 7:09 PM \u00a0 \u00a0 \u00a0\u00a0 etc\nd----- 4\/12\/16 8:14 PM \u00a0 \u00a0 \u00a0\u00a0 home\nd----- 9\/14\/17 5:16 AM \u00a0 \u00a0 \u00a0\u00a0 lib\nd----- 8\/2\/17 2:09 PM \u00a0 \u00a0 \u00a0 \u00a0 lib64\nd----- 8\/2\/17 2:09 PM \u00a0 \u00a0 \u00a0 \u00a0 media\nd----- 8\/2\/17 2:09 PM \u00a0 \u00a0 \u00a0 \u00a0 mnt\nd----- 9\/14\/17 5:16 AM \u00a0 \u00a0 \u00a0\u00a0 opt\nd-r--- 9\/17\/17 7:09 PM \u00a0 \u00a0 \u00a0\u00a0 proc\nd----- 9\/17\/17 7:09 PM \u00a0 \u00a0 \u00a0\u00a0 root\nd----- 8\/2\/17 2:09 PM \u00a0 \u00a0 \u00a0 \u00a0 run\nd----- 9\/13\/17 3:58 AM \u00a0 \u00a0 \u00a0\u00a0 sbin\nd----- 8\/2\/17 2:09 PM \u00a0 \u00a0 \u00a0 \u00a0 srv\nd-r--- 9\/17\/17 7:09 PM \u00a0 \u00a0 \u00a0\u00a0 sys\nd----- 9\/17\/17 7:09 PM \u00a0 \u00a0 \u00a0\u00a0 tmp\nd----- 9\/14\/17 5:17 AM \u00a0 \u00a0 \u00a0\u00a0 usr\nd----- 9\/14\/17 5:16 AM \u00a0 \u00a0 \u00a0\u00a0 var\nPS \/&gt; $PSVersionTable\nName \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Value\n---- \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 -----\nPSVersion \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0 6.0.0-beta\nPSEdition \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0 Core\nGitCommitId \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0 v6.0.0-beta.7\nOS \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Linux 4.9.41-moby #1 SMP Wed Sep 6 00:05:16 UTC 2017\nPlatform \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Unix\nPSCompatibleVersions \u00a0 \u00a0 \u00a0 {1.0, 2.0, 3.0, 4.0...}\nPSRemotingProtocolVersion\u00a0 2.3\nSerializationVersion \u00a0 \u00a0 \u00a0 1.1.0.1\nWSManStackVersion \u00a0 \u00a0 \u00a0 \u00a0\u00a0 3.0\nPS \/&gt; exit\nPS C:\\&gt; # back to a Windows prompt\n<\/code><\/p>\n<p><strong>I just typed 2 commands and I now have a new operating system, in a tiny container, running on my local machine! <\/strong>Just docker pull and docker run; that&#8217;s it!<\/p>\n<p>Here&#8217;s exactly what happened:<\/p>\n<ul>\n<li>docker pull downloaded an image, and tagged ubuntu16.04, from the microsoft\/powershell repository.<\/li>\n<li>docker run created a new container from that local image, started it, and ran the command powershell. This launched a PowerShell shell in the container. You can see the &#8220;PowerShell v6.0.0-beta.7&#8243;\u009d header.<\/li>\n<li>In the container, dir displays a decidedly Unix\u2014not Windows\u2014folder listing. However, the format of the directory listing is the default PowerShell layout of content, with Mode, LastWriteTime, Length, and Name fields.<\/li>\n<li>$PSVersionTable displays version information about PowerShell. Note that the platform is Unix.<\/li>\n<li>Typing exit closed the connection to the container, stopped the container, and returned us to a normal Windows PowerShell command prompt.<\/li>\n<\/ul>\n<p>(FYI, the docker run -i -t options create an interactive terminal with the container. Learn more at <a target=\"_blank\" href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/run\/\" rel=\"noopener noreferrer\">Docker&#8217;s documentation<\/a>.)<\/p>\n<h2>Listing containers<\/h2>\n<p>So we just created a container, but where is it? We display containers with the docker ps command.<\/p>\n<p style=\"padding-left: 60px\"><code>\nPS C:\\&gt; docker ps\nCONTAINER ID \u00a0\u00a0 IMAGE \u00a0\u00a0 STATUS \u00a0\u00a0 NAMES\nPS C:\\&gt; # no containers?\n<\/code><\/p>\n<p>Um&#8230;what? Ah, like the Unix <strong>ps<\/strong> command, the docker ps command by default shows only <em>running<\/em> containers. We need to run docker ps -a to show all containers.<\/p>\n<p style=\"padding-left: 60px\"><code>\nPS C:\\&gt; docker ps -a\nCONTAINER ID   IMAGE \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0 STATUS \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0 NAMES\nd05a481fcbf1   microsoft\/powershell:ubuntu16.04   Exited (0) 20 seconds ago \u00a0 \u00a0 blissful_kepler\nPS C:\\&gt;\n<\/code><\/p>\n<p>(Docker command output in the walkthrough has been edited for display purposes.)<\/p>\n<p>In this simple container listing:<\/p>\n<ul>\n<li>You can see the image named used to create the container, and that it&#8217;s not running: <strong>Status<\/strong> = &#8216;Exited&#8217;.<\/li>\n<li><strong>Container ID<\/strong> has a unique value that can be used to identify and manage the container.<\/li>\n<li><strong>Names<\/strong> also has a unique value, <strong>blissful_kepler<\/strong> (two random strings combined together), that can be used to identify and manage the container.<\/li>\n<\/ul>\n<h2>Creating a container with a specific name<\/h2>\n<p>If you create a container, but don&#8217;t specify a name, Docker creates a random name for you. And while that random value is easier to work with than the Container ID value, it&#8217;s not ideal if we are going to work with the container over and over. Let&#8217;s create a new container named <strong>MyContainer<\/strong> from the same image, and start it up.<\/p>\n<p style=\"padding-left: 60px\"><code>\nPS C:\\&gt; # specify --name to create container with a specific name\nPS C:\\&gt; docker run -i -t --name MyContainer microsoft\/powershell:ubuntu16.04 powershell\nPowerShell v6.0.0-beta.7\nCopyright (C) Microsoft Corporation. All rights reserved.\nPS \/&gt; # we are back in a container; note the PS \/&gt; prompt\nPS \/&gt; # but let\u2019s just exit for now\nPS \/&gt; exit\nPS C:\\&gt;\n<\/code><\/p>\n<p>So now let&#8217;s take another quick look at the container list:<\/p>\n<p style=\"padding-left: 60px\"><code>\nPS C:\\&gt; docker ps -a\nCONTAINER ID   IMAGE \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0 STATUS \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0 NAMES\nffa33fdae088   microsoft\/powershell:ubuntu16.04   Exited (0) 10 seconds ago   MyContainer\nd05a481fcbf1   microsoft\/powershell:ubuntu16.04   Exited (0) 5 minutes ago    blissful_kepler\n<\/code><\/p>\n<p>Now we have two containers, both created from image microsoft\/powershell:ubuntu16.04.<\/p>\n<h2>Stopping and removing a container<\/h2>\n<p>At this point, let&#8217;s get rid of container blissful_kepler. First, make sure it&#8217;s stopped with docker stop, and then remove it with docker rm.<\/p>\n<p style=\"padding-left: 60px\"><code>\nPS C:\\&gt; # if you run stop and it\u2019s already stopped, that\u2019s OK\nPS C:\\&gt; docker stop blissful_kepler\nblissful_kepler\nPS C:\\&gt; docker rm blissful_kepler\nblissful_kepler\nPS C:\\&gt; docker ps -a\nCONTAINER ID   IMAGE \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0 STATUS \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 NAMES\nffa33fdae088   microsoft\/powershell:ubuntu16.04   Exited (0) 2 minutes ago   MyContainer\nPS C:\\&gt; # only MyContainer is left\n<\/code><\/p>\n<h2>Copying content into a container<\/h2>\n<p>So far, this container has been helpful if you want to test small, ad-hoc commands on another operating system. But if you really want to test any preexisting code, you need to copy that code into the container and run it within the container. So let&#8217;s copy over the entire PowerShell Beautifier project. On my local machine, the Beautifier is located at C:\\code\\GitHub\\PowerShell-Beautifier. We&#8217;ll copy that folder into <strong>MyContainer<\/strong>, under the container&#8217;s \/tmp path. To do this, we use the docker cp command.<\/p>\n<p style=\"padding-left: 60px\"><code>\nPS C:\\&gt; # running this in Windows PowerShell, not from within the container\nPS C:\\&gt; docker cp C:\\Code\\GitHub\\PowerShell-Beautifier MyContainer:\/tmp\n<\/code><\/p>\n<h2>Starting and reconnecting to a container<\/h2>\n<p>Now reconnect to <strong>MyContainer<\/strong> to confirm the PowerShell-Beautifier folder content is there. When we first created <strong>MyContainer<\/strong>, we used docker run -i -t [image name] powershell to create it from the image and start it. Now that we have <strong>MyContainer<\/strong>, we just need to start it with docker start, and then reconnect to it with docker <strong>exec<\/strong> -i -t [<strong>container name<\/strong>] powershell. This creates an interactive terminal with a PowerShell shell.<\/p>\n<p style=\"padding-left: 60px\"><code>\nPS C:\\&gt; # first we need to start the container\nPS C:\\&gt; # if you run start and it\u2019s already started, that\u2019s OK\nPS C:\\&gt; docker start MyContainer\nMyContainer\nPS C:\\&gt; # let\u2019s make sure it\u2019s running\nPS C:\\&gt; docker ps -a\nCONTAINER ID   IMAGE \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0 STATUS \u00a0 \u00a0 \u00a0\u00a0 NAMES\nffa33fdae088   microsoft\/powershell:ubuntu16.04   Up 11 seconds   MyContainer\nPS C:\\&gt; # because it\u2019s running we don't need to add the -a to see it\nPS C:\\&gt; docker ps\nCONTAINER ID   IMAGE \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0 STATUS \u00a0 \u00a0 \u00a0\u00a0 NAMES\nffa33fdae088   microsoft\/powershell:ubuntu16.04   Up 20 seconds   MyContainer\nPS C:\\&gt; # now connect\nPS C:\\&gt; docker exec -i -t MyContainer powershell\nPowerShell v6.0.0-beta.7\nCopyright (C) Microsoft Corporation. All rights reserved.\nPS \/&gt; # we are back in the container; note the PS \/&gt; prompt\n<\/code><\/p>\n<h2>Confirming folder now exists in MyContainer<\/h2>\n<p>To confirm the content is there, change the directory to \/tmp\/PowerShell-Beautifier, and get a directory listing:<\/p>\n<p style=\"padding-left: 60px\"><code>\nPS \/&gt; # we are inside MyContainer\nPS \/&gt; cd \/tmp\/PowerShell-Beautifier\nPS \/tmp\/PowerShell-Beautifier&gt; dir\nDirectory: \/tmp\/PowerShell-Beautifier\nMode \u00a0 LastWriteTime \u00a0 \u00a0 Length \u00a0 Name\n---- \u00a0 ------------- \u00a0 \u00a0 ------ \u00a0 ----\nd-----          9\/11\/17  11:14 PM \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 docs\nd-----          9\/11\/17  10:11 PM \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 src\nd-----          9\/11\/17  10:11 PM \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 test\n------          6\/11\/17   4:05 PM \u00a0 1086 \u00a0 \u00a0 LICENSE\n------           9\/9\/17   9:54 PM \u00a0\u00a0 7638 \u00a0 \u00a0 README.md\nPS \/tmp\/PowerShell-Beautifier&gt; # nice!\n<\/code><\/p>\n<h2>Running a test script inside MyContainer<\/h2>\n<p>Now let&#8217;s test a PowerShell script <em>inside<\/em> the container. The PowerShell Beautifier project comes with a test script \/test\/Invoke-DTWBeautifyScriptTests.ps1. This script runs a series of reformatting tests to make sure the Beautifier works correctly for different scenarios. Let&#8217;s run this script in MyContainer.<\/p>\n<p style=\"padding-left: 60px\"><code>\nPS \/tmp\/PowerShell-Beautifier&gt; # we are inside MyContainer\nPS \/tmp\/PowerShell-Beautifier&gt; cd test\nPS \/tmp\/PowerShell-Beautifier\/test&gt; .\/Invoke-DTWBeautifyScriptTests.ps1\nImporting beautifier module: DTW.PS.Beautifier\nProcessing folder: Case\nFile: Commands.ps1\nFile: Members.ps1\nFile: ParameterAttributes.ps1\nFile: Parameters.ps1\nFile: Types.ps1\nProcessing folder: CompleteFiles\nFile: Clear-PSFSitecoreRecycleBin.ps1\nFile: Remove-PSFOldContent.ps1\nProcessing folder: FileEncoding\nFile: ASCII_NoBOM.ps1\nFile: UTF16_BE_BOM.ps1\nFile: UTF16_BE_NoBOM.ps1\nFile: UTF16_LE_BOM.ps1\nFile: UTF16_LE_NoBOM.ps1\nFile: UTF8_BOM.ps1\nFile: UTF8_NoBOM.ps1\nProcessing folder: Rename\nFile: Alias.ps1\nProcessing folder: Whitespace\nFile: CmdletDefinition.ps1\nFile: DotSource.ps1\nFile: NoNewLineAtEndOfFile.ps1\nFile: NonWindowsLineEnding.ps1\nFile: WithinLine.ps1\nFile: Indentation.ps1\nFile: Indentation.ps1\nFile: Indentation.ps1\nAll tests passed - woo-hoo!\nPS \/tmp\/PowerShell-Beautifier\/test&gt;\n<\/code><\/p>\n<p>Invoke-DTWBeautifyScriptTests.ps1 also has a -Quiet option. If the test script runs without any errors, then only Boolean $true is returned at the end. This is helpful for automating the test script described in the next section.<\/p>\n<p style=\"padding-left: 60px\"><code>\nPS \/tmp\/PowerShell-Beautifier\/test&gt; # we are inside MyContainer\nPS \/tmp\/PowerShell-Beautifier\/test&gt; # run the script sans output\nPS \/tmp\/PowerShell-Beautifier\/test&gt; .\/Invoke-DTWBeautifyScriptTests.ps1 -Quiet\nTrue\nPS \/tmp\/PowerShell-Beautifier\/test&gt; exit\n<\/code><\/p>\n<h2>Automating the testing process<\/h2>\n<p>Running all these Docker commands manually is a good way to learn the Docker command line interface. It&#8217;s also a good way to get inside a PowerShell Core instance for another operating system, to try some small commands. But if you want to use these Docker images to automate testing of your existing PowerShell scripts, you would need to automate all the steps above. And you would want to be able to:<\/p>\n<ul>\n<li>Specify one or more source paths to copy into a container.<\/li>\n<li>Specify which test script to run in the container.<\/li>\n<li>Specify which Docker images to test against, and validate they exist.<\/li>\n<li>Create missing containers for the images we specify, start containers when we need to, and stop them when we&#8217;re done.<\/li>\n<li>Maybe even allow the override of the default Docker Hub project with something other than microsoft\/powershell.<\/li>\n<\/ul>\n<p>There&#8217;s actually a script ready for you right now that does all this! Its name is Invoke-RunTestScriptInDockerCoreContainers.ps1, and it&#8217;s in the <a target=\"_blank\" href=\"https:\/\/github.com\/DTW-DanWard\/PowerShell-Beautifier\" rel=\"noopener noreferrer\">PowerShell Beautifier<\/a> project under <a target=\"_blank\" href=\"https:\/\/github.com\/DTW-DanWard\/PowerShell-Beautifier\/tree\/master\/test\/Automation\" rel=\"noopener noreferrer\">\/test\/Automation<\/a>. Check out the readme, or go <a target=\"_blank\" href=\"https:\/\/github.com\/DTW-DanWard\/PowerShell-Beautifier\/blob\/master\/test\/Automation\/Invoke-RunTestScriptInDockerCoreContainers.ps1\" rel=\"noopener noreferrer\">straight to the source<\/a> yourself. Feel free to copy the script, or clone and fork\u00a0the entire project if you&#8217;d like to try out the PowerShell Beautifier yourself.<\/p>\n<p>First, let&#8217;s pull another image from Docker Hub. Let&#8217;s get the centos7 image.<\/p>\n<p style=\"padding-left: 60px\"><code>\nPS C:\\&gt; docker pull microsoft\/powershell:centos7\ncentos7: Pulling from microsoft\/powershell\n2d490773b5db: Pull complete\n8cd0d9ccbcbc: Pull complete\nf54c59906966: Pull complete\n963d4e7132af: Pull complete\n98f59503f09a: Pull complete\nDigest: sha256:a6fdb2a29195f3280cb4df171f8fbabc20d0e6fbee8bb4b2fd9de66e1f16c33e\nStatus: Downloaded newer image for microsoft\/powershell:centos7\nPS C:\\&gt;\n<\/code><\/p>\n<p>Now let&#8217;s run Invoke-RunTestScriptInDockerCoreContainers.ps1. By default, if you copy the entire Beautifier project, you may not need to specify any values for the parameters. The default values for the script parameters should cover everything. The only thing you might want to specify is -TestImageNames, which currently defaults to ubuntu16.04, centos7, and opensuse42.1. But just to show you the parameters in action, we&#8217;ll specify -SourcePaths, -TestFileAndParams and -TestImageNames.<\/p>\n<p>Just to be clear: currently on my machine I have images for ubuntu16.04 and centos7, but not opensuse42.1.<\/p>\n<p style=\"padding-left: 60px\"><code>\nPS C:\\&gt; # running this in Windows PowerShell, not from within the container\nPS C:\\&gt; C:\\code\\GitHub\\PowerShell-Beautifier\\test\\Automation\\Invoke-RunTestScriptInDockerCoreContainers.ps1 `\n&gt;&gt; -SourcePaths C:\\Code\\GitHub\\PowerShell-Beautifier `\n&gt;&gt; -TestFileAndParams 'PowerShell-Beautifier\/test\/Invoke-DTWBeautifyScriptTests.ps1 -Quiet' `\n&gt;&gt; -TestImageNames @('ubuntu16.04','centos7','opensuse42.1')\nTesting with these values:\nTest file:        PowerShell-Beautifier\/test\/Invoke-DTWBeautifyScriptTests.ps1 -Quiet\nDocker hub repo:  microsoft\/powershell\nImages names:     ubuntu16.04 centos7 opensuse42.1\nSource paths:     C:\\Code\\GitHub\\PowerShell-Beautifier\nImage opensuse42.1 is not installed locally but exists in repository microsoft\/powershell\nTo download and install type:\ndocker pull microsoft\/powershell:opensuse42.1\nTesting on these containers: ubuntu16.04 centos7\nubuntu16.04\nPreexisting container found\nStarting container\nGetting temp folder path in container\nCopying source content to container temp folder \/tmp\/\nC:\\Code\\GitHub\\PowerShell-Beautifier\nRunning test script on container\nTest script completed successfully\nStopping container\ncentos7\nPreexisting container not found; creating and starting\nGetting temp folder path in container\nCopying source content to container temp folder \/tmp\/\nC:\\Code\\GitHub\\PowerShell-Beautifier\nRunning test script on container\nTest script completed successfully\nStopping container\nPS C:\\&gt; # the test script ran correctly in all containers! woo-hoo!\n<\/code><\/p>\n<h2>Conclusion<\/h2>\n<p>As you can see, Docker is a simple and powerful technology for packaging and distributing software. While this article focused on just using the PowerShell Core images, you should check out the <a target=\"_blank\" href=\"https:\/\/hub.docker.com\/explore\/\" rel=\"noopener noreferrer\">Docker Hub<\/a> to see what other images exist. You can also learn more about how to incorporate Docker into your development processes.<\/p>\n<p>Also, feel free to submit a ticket if you have an issue or enhancement request for the test script or the PowerShell Beautifier. And feel free to <a target=\"_blank\" href=\"http:\/\/dtwconsulting.com\/\" rel=\"noopener noreferrer\">contact me<\/a>.<\/p>\n<p>Thank you for your time and interest!<\/p>\n<p>Dan Ward, guest blogger<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; Summary: Learn the basics about Docker, and see how to use it for PowerShell Core script testing on different operating systems. I&#8217;m Dan Ward, a Boston-based .NET software engineer who is just plum crazy about PowerShell and automation. Earlier this year, I uploaded my first GitHub project\u2014a PowerShell whitespace cleaner that also replaces aliases [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[568],"tags":[704,56,377,3],"class_list":["post-82495","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hey-scripting-guy","tag-docker","tag-guest-blogger","tag-powershell","tag-scripting-guy"],"acf":[],"blog_post_summary":"<p>&nbsp; Summary: Learn the basics about Docker, and see how to use it for PowerShell Core script testing on different operating systems. I&#8217;m Dan Ward, a Boston-based .NET software engineer who is just plum crazy about PowerShell and automation. Earlier this year, I uploaded my first GitHub project\u2014a PowerShell whitespace cleaner that also replaces aliases [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/82495","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=82495"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/82495\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=82495"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=82495"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=82495"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}