Многократно используемые модули PowerShell с Pester: полное руководство

Последнее обновление: 17/12/2025
Автор: Исаак
  • Преобразуйте функции в модули. PowerShell Манифест позволяет легко повторно использовать, создавать версии и распространять их.
  • Pester предоставляет возможности модульного и интеграционного тестирования для проверки модулей и скриптов, предотвращая регрессии при будущих изменениях.
  • Интеграция PowerShell, Pester и PowerShellGet в конвейеры CI/CD автоматизирует тестирование, проверку синтаксиса и публикацию в PowerShell Gallery.

многократно используемые модули PowerShell с помощью Pester

Если вы ежедневно работаете с PowerShell, рано или поздно вам надоест постоянно копировать и вставлять одни и те же функции. Вот тогда-то и имеет смысл поговорить о... Многократно используемые модули PowerShell и как их серьезно протестировать с помощью Pester.точно так же, как и в случае с любым "серьезным" проектом развития.

Хотя PowerShell изначально разрабатывался как инструмент администратора, сегодня он является... Полноценный кроссплатформенный язык автоматизации с мощной экосистемой.Модули, расширенные возможности написания скриптов, автоматизированное тестирование, CI/CD... и если вы знаете, как упаковывать свои функции в хорошо структурированные модули, поддерживаемые Pester, вы можете версионировать, обмениваться файлами, публиковать в PowerShell Gallery и развертывать приложения с уверенностью, не прилагая особых усилий при каждом изменении строки кода.

Что именно представляет собой модуль PowerShell и чем он отличается от скрипта?

Основные понятия модулей PowerShell

Модуль PowerShell — это, проще говоря, пакет с команды Повторно используемые: функции, командлеты, псевдонимы, переменные, классы или ресурсы DSC.Особенность модуля заключается в том, что PowerShell может загружать и выгружать его, контролировать то, что доступно пользователю, назначать ему версию, автора, зависимости и т. д.

С точки зрения файловой системы, типичный модуль состоит как минимум из... файл .psm1 (код) и, почти всегда, манифест .psd1 с метаданными.В него также могут входить другие скрипты, ресурсы, файлы справки, данные и т. д. При импорте с помощью Import-Module или, благодаря автоматической загрузке, ваши команды становятся доступны так, как если бы они были встроенными.

Вместо этого скрипт PowerShell — это просто Файл .ps1, который запускается «все сразу».Он может содержать функции, но эти функции обычно находятся в области видимости скрипта. Если вы не используете точечные источники или не помещаете их в модуль, они исчезают сразу после завершения выполнения.

Практическая разница существенна: сценарии обычно «Задачи, которые запускаются», в то время как модули являются «многоразовые библиотеки» которые можно использовать из других скриптов, из консоли или даже из конвейеров CI/CD без дублирования кода.

Скрипты против модулей: когда использовать каждый из них?

Различия между скриптами и модулями PowerShell.

Un скрипт (.ps1) Это идеально подходит, когда нужно решить конкретные задачи: а) резервная копияОтчет, запланированная уборка… Вы запускаете его, он выполняет свою работу и завершается. Если вы определяете функции внутри этого скрипта, эти функции будут находиться в файле. область действия скриптаПо завершении процесса область видимости удаляется, а вместе с ней и ваши функции.

Un скриптовый модуль (.psm1)Вместо этого, он предназначен для инкапсуляции функций, которые вы будете многократно использовать на разных машинах и даже в разных проектах. Храня их в модуле, Они загружаются в рамках модуля, и вы можете экспортировать в качестве публичного API только то, что вам необходимо..

Многие администраторы начинают с огромного скрипта, который делает всё, и с El TiempoОни видят, что постоянно используют одни и те же части этого кода. Естественным следующим шагом является... Вынесите эти повторяющиеся функции в модуль.Оставьте их протестированными с помощью Pester, и пусть этот модуль станет основой для других, более мелких и чистых скриптов.

Кроме того, модули обеспечивают работу ключевого элемента оборудования: версионирование, публикация и распространениеВы можете устанавливать модули из PowerShell Gallery, из частных репозиториев, из локальных репозиториев или даже встраивать их в образы системы, чтобы они были доступны по умолчанию.

Использование точечного исходного кода: «быстрый трюк» перед переходом к модулям.

Прежде чем размещать функции в модуле, вы можете разместить их в простом файле. скрипт .ps1, который вы хотите использовать повторноВ таком случае единственный приемлемый способ сделать их доступными в вашей сессии — использовать точечное копирование.

Когда вы запускаете скрипт с . MyScript.ps1Содержимое обрабатывается в рамках скрипта. Если в этом файле есть функции, они исчезают после завершения работы скрипта. Однако, если вы вызываете его с помощью точка и пробел перед (dot-source)PowerShell выполняет его в глобальной области видимости, и функции загружаются:

Примеры использования .sourcing для загрузки функций в память:

  • Загрузка с использованием относительного пути: . .\Get-MrPSVersion.ps1
  • Загрузка с полным маршрутом: . C:\Demo\Get-MrPSVersion.ps1
  • Загрузка с использованием переменной пути: $Path = 'C:\'; . $Path\Get-MrPSVersion.ps1

После выполнения команды `dot-sourcing` вы можете убедиться, что функция существует в модуле. Назначение: с Get-ChildItem -Path Function:\Get-MrPSVersionКак теперь это часть глобальной сферы..

Проблема в том, что такой подход плохо масштабируется: Нам нужно помнить о необходимости использовать точечный исходный код; у вас нет версии, нет манифеста, нет различия между публичным и частным контентом.Это полезный приём, но для чего-то серьёзного и доступного для совместного использования гораздо лучше перейти к использованию скриптовых модулей.

Создание скриптовых модулей и их автоматическая загрузка.

создание скриптовых модулей и автоматическая загрузка

В PowerShell создание скриптового модуля — это очень просто: Это файл .psm1, содержащий ваши функции.Например, если вы создадите файл MyScriptModule.psm1 с чем-то вроде:

function Get-MrPSVersion { $PSVersionTable }
function Get-MrComputerName { $env:COMPUTERNAME }

а затем вы пытаетесь использовать Get-MrComputerName, вы увидите, что Он обнаруживается только после импорта модуля.Это можно сделать вручную с помощью:

  Советы о том, как настроить принтер для облачной печати Google

Import-Module C:\MyScriptModule.psm1

Волшебство PowerShell раскрылось с появлением PowerShell 3. самозагрузка модулейДля того чтобы это сработало, необходимо:

  • Сохраните свой модуль в папке, базовое имя которой совпадает с именем модуля, например. MyScriptModule\MyScriptModule.psm1.
  • Поместите эту папку в какой-либо путь. $env:PSModulePath.

Значение $env:PSModulePath Это список маршрутов, разделенных по ;Вы можете просмотреть его в читаемом виде с помощью:

$env:PSModulePath -split ';'

Типичные пути включают папку модулей пользователя, глобальную папку модулей. Program Files и система в System32. Обычно это Установите свои собственные модули в каталог "AllUsers" (Program Files). а System32-модульный оставьте только для системных модулей.

После установки модуля, При первом запуске одной из этих команд PowerShell автоматически загрузит её. без необходимости вручную вызывать Import-Module, что очень удобно в скриптах и ​​интерактивных сессиях.

Манифест модуля: метаданные, версия и экспорт функций.

Для корректного определения модуля недостаточно файла .psm1: Вам нужен манифест в формате .psd1.Это всего лишь файл данных PowerShell, содержащий метаданные модуля (имя, версия, автор, описание, зависимости, экспортируемые функции и т. д.).

Стандартный способ его создания — это использование New-ModuleManifestпо крайней мере сдать Тропа из файла .psd1 и параметра Корневой модуль указывает на файл .psm1. Кроме того, если вы планируете опубликовать модуль в репозитории, таком как PowerShell Gallery, Поля, такие как Автор, Описание или Название компании, являются обязательными..

Один из признаков отсутствия манифеста в вашем модуле — проверка его версии с помощью команды `make version`. Get-Module -Name MyScriptModule и увидеть номер версии 0.0Это явный признак того, что существует только один отдельный файл .psm1 без связанного с ним файла .psd1.

Типичный образец Для создания манифеста это выглядело бы примерно так:

$moduleManifestParams = @{
Path = "$env:ProgramFiles\WindowsPowerShell\Modules\MyScriptModule\MyScriptModule.psd1"
RootModule = 'MyScriptModule'
Author = 'Autor del módulo'
Description = 'Funciones reutilizables para administración'
CompanyName = 'MiEmpresa'
}
New-ModuleManifest @moduleManifestParams

В дальнейшем, если вам потребуется изменить какие-либо данные, вместо того чтобы создавать манифест заново (что приведет к генерации нового файла манифеста), вы сможете это сделать. новый GUID и может нарушать зависимости), правильным вариантом будет использовать Update-ModuleManifest Изменять только то, что необходимо.

Манифест также включает в себя такие ключевые разделы, как... Функции для экспортагде можно точно указать, какие функции модуля доступны пользователю, а остальные оставить без изменений. внутренние частные функции к модулю.

Общедоступные и частные функции в ваших модулях

В реальном модуле нежелательно раскрывать все возможности. Это нормально. внутренние вспомогательные функции, которые используются только друг другом.и что вы не хотите, чтобы пользователи звонили напрямую. Существует два основных способа контролировать то, что уходит «вовне»:

Если у вас нет манифеста (простой модуль, содержащий только файл .psm1), вы можете управлять видимостью с помощью Export-ModuleMember внутри самого файла .psm1. Например:

function Get-MrPSVersion { $PSVersionTable }
function Get-MrComputerName { $env:COMPUTERNAME }
Export-ModuleMember -Function Get-MrPSVersion

В этом случае, только Команда Get-MrPSVersion будет отображаться как команда модуля.В то время как Функция Get-MrComputerName по-прежнему будет доступна из других функций модуля, но не будет экспортироваться публично.Проверить, какие команды доступны, можно с помощью следующей команды:

Get-Command -Module MyScriptModule

Если у вас есть манифест, то самый простой способ — определить этот список в ключе. Функции для экспорта Например, из файла .psd1:

FunctionsToExport = 'Get-MrPSVersion'

Нет необходимости дублировать логику, используя оба подхода одновременно. Export-ModuleMember в файле .psm1 и FunctionsToExport в файле .psd1Любой из этих двух механизмов является достаточным. Подход, основанный на манифесте, обычно более ясен в среднесрочной перспективе.

Галерея PowerShell: требования и публикация модулей и скриптов.

La Галерея PowerShell Это основной общедоступный репозиторий для модулей и скриптов. Оттуда вы устанавливаете зависимости с помощью команды `npm install`. Install-Moduleвы обновляете с помощью Update-Module и вы публикуете свои собственные пакеты с помощью Publish-Module o Publish-Script.

Для публикации модуля необходимо выполнить ряд действий. минимальные требования Важно помнить о следующих моментах: уникальное имя, семантическая версия, корректный манифест, заполненные основные метаданные и, если вы используете зависимости, их доступность. Аналогично, это относится и к скриптам, которые вы хотите опубликовать. Им нужен заголовок с метаданными в формате скриптового файла. (автор, описание, версия и т. д.).

Связь между PowerShellGet, PackageManagement и NuGet Примерно так это работает: PowerShellGet — это используемый вами модуль (Install-Module, Publish-Module…), PackageManagement — это общий уровень управления пакетами, а под всем этим, для галереи, вы используете NuGet как поставщикЭто означает, что, несмотря на то, что бэкэнд использует NuGet, его использование не одно и то же. nuget.exe что вы используете PowerShellGet; для большинства задач модулей PowerShell вы всегда будете использовать командлеты PowerShellGet.

Для публикации вам необходимо Ключ API NuGet (NUGET_KEY) используется в качестве учетных данных. В средах CI/CD он хранится как секрет и предоставляется во время сборки для выполнения команды. Publish-Module -NuGetApiKey, Вы также можете заявить о принадлежности посылки, зарезервировать имена или сообщить о нарушениях условий лицензии непосредственно в Галерее, следуя ее маршрутам.

  Как выполнить испытание «Гонг» в Fortnite

Что такое Pester и почему его следует использовать с вашими модулями?

Назойливый — это стандартная среда для модульного и интеграционного тестирования PowerShellЭто модуль, написанный на PowerShell, который определяет очень читаемый язык тестирования на основе блоков, например... Опишите, контекст, это, прежде всего, после всего и в таких утверждениях, как Должно быть, не должно быть, и т.д.

Цель Пестера состоит в том, чтобы Каждый раз, когда вы вносите изменения в свой код, вы можете запустить набор автоматизированных тестов. Это гарантирует, что вы будете и дальше соответствовать ожидаемому поведению. Это позволяет избежать многих распространенных проблем: исправление одной проблемы в рабочей среде приводит к поломке другой, или изменение аутентификации в крупном проекте может привести к сбою половины платформы, о котором никто не догадается.

На практике Pester позволяет охватить оба варианта. модульные тесты (изолированные функции, с заглушками там, где это необходимо) например интеграционное тестирование (ваш модуль взаимодействует с SharePoint(Azure, SQL и т. д.). Для многих организаций, Проведение тестов с помощью Pester является минимальным стандартом качества.даже для «простых» административных скриптов.

Помимо утверждений, Пестер предлагает следующее: логическая группировка тестов, имитация внешних команд и измерение покрытия кодаЭто позволяет наглядно увидеть, какие части модуля изучаются, а какие нет.

Установка и базовое использование Pester с модулями.

Современные версии Windows они обычно приносят Предустановлена ​​старая версия Pester (v3).В настоящее время обычно устанавливают обновленную версию из Галереи с помощью следующей команды:

Install-Module -Name Pester -Force

Пестер работает в Windows, Linux и macOS Он совместим с PowerShell 3, 4, 5, 6 и 7, поэтому у вас не возникнет проблем в смешанных средах. После установки вам останется только создать тестовые файлы с расширением .Tests.ps1 или .Test.ps1 которые описывают поведение ваших модулей.

La типичная структура Тестовый файл содержит такие блоки, как:

  • Прежде всегоЭта команда выполняется один раз перед всеми тестами (идеально подходит для импорта модуля или определения общих данных).
  • Описывать: группы тестов для проверки функции или области функциональности.
  • Контекст: подразделяет сценарии («когда параметры верны», «когда возникает ошибка учетных данных»…).
  • ItКаждый блок It представляет собой отдельное доказательство со своим набором утверждений, использующих Должен.
  • После всего: выполнить очистку в конце всех тестов (закрыть соединения, удалить временные файлы и т. д.).

Для запуска тестов просто позвоните Invoke-Pester Указав путь к тестовому файлу или папке, вы получите сводку количества успешных и неудачных проверок, а также время выполнения и, при желании, подробный вывод. -Подробный вывод.

Практический пример: тестирование функции авторизации с помощью Pester.

Представьте себе функцию PowerShell, которая называется LoginSP Эта функция инкапсулирует вход в SharePoint Online с использованием Plug and Play (PnP) или CSOM и возвращает контекст SharePoint. Эта функция находится в вашем модуле или в файле .ps1, который вы используете во многих сценариях автоматизации.

Если от этого зависят десятки бизнес-функций, Нельзя допустить, чтобы изменение реализации (например, переход с PnP на CSOM) сломало всё.Разумнее всего будет писать модульные тесты с помощью Pester в отдельном файле. LoginSharePoint.Test.ps1 или похожие.

В этом тестовом файле, в блоке Прежде всего Обычно используется dot-sourcer или импорт модуля с помощью функции LoginSP. Затем создается один или несколько блоков. Опишите процесс "Тестирование LoginSP" и в контексте различных сценариев: правильные параметры, неправильные параметры, неверные учетные данные и т. д.

Каждый блок It Он содержит специфический тест, например: «не должен возвращать null» или «URL возвращаемого контекста совпадает с входным URL». В одном тесте можно вызвать функцию непосредственно внутри пайпа Should, в другом сохранить результат в переменной для проверки свойств и записи дополнительной информации. Write-Host если бы я ошибался.

Выполнение осуществляется с помощью Invoke-Pester ".\LoginSharePoint.Test.ps1" А если вам нужны более подробные сведения, вы можете добавить -Output DetailedПомимо мгновенного вывода результатов, Pester может быть интегрирован с покрытие кода чтобы увидеть, какие части модуля были выполнены во время тестирования.

Входные параметры в тестах Pester и использование контейнера.

Вставка учетных данных или URL-адресов непосредственно в каждый тест — это настоящий кошмар с точки зрения обслуживания, и, кроме того, автоматизировать этот процесс сложно. Элегантный подход с помощью Pester заключается в... Параметры объявляются непосредственно в тестовом файле.Точно так же, как и в скрипте PowerShell:

Param (
[Parameter(Mandatory=$true)] [string]$UserAccount,
[Parameter(Mandatory=$true)] [string]$UserPW,
[Parameter(Mandatory=$true)] [string]$SiteCollUrl
)

С помощью этого вы можете использовать это внутри теста. $UserAccount, $UserPW и $SiteCollUrl Во всех тестах, без их повторения. Для передачи этих значений при запуске тестов Pester предоставляет... PesterContainer:

$myContainer = New-PesterContainer -Path 'LoginSharePoint.Test.ps1' -Data @{
UserAccount = '[email protected]';
UserPw = 'MiMuySeguraPW';
SiteCollUrl = 'https://tenant.sharepoint.com/sites/TeamSite'
}
Invoke-Pester -Container $myContainer -Output Detailed

Таким образом вы можете Внедрять различные тестовые данные, не изменяя тестовый код.Это идеально подходит для конвейеров непрерывной интеграции, где учетные данные, URL-адреса или данные арендаторов меняются в зависимости от среды (разработка, предпроизводство) и передаются в виде секретов или защищенных переменных.

  Решение: полностью решено: невозможно получить доступ к панели управления Nvidia в Windows 10, 8.1 или 7.

Модульное и интеграционное тестирование: что включает в себя каждый вид тестирования.

В мире Пестера важно различать модульные тесты y интеграционное тестированиеВ унитарных школах основное внимание уделяется небольшие блоки кода изолированноОбычно с использованием имитаций внешних зависимостей. Например, функция «New-Drawer» должна возвращать объект выдвижной панели с четырьмя углами, двумя направляющими, ручкой, правильным цветом и правильными размерами.

Интеграционные тесты, в свою очередь, подтверждают, что Все эти отдельные компоненты корректно функционируют при подключении к реальным системам.SharePoint, базы данныхвнешние сервисы и т. д. Вы можете получить все модульные тесты в хорошем состоянии, но интеграция может обернуться катастрофой, если вы не протестируете её явно (например, если среда, в которой настроен "бокс", не подходит).

В PowerShell часто бывает так, что ваши модули инкапсулируют всю бизнес-логику, и Pester помогает вам в этом... обеспечить, чтобы каждая функция выполняла свою задачу (унитарность). Как, например Совместная работа функций, модулей и внешних сервисов (интеграция).

Главное преимущество заключается в том, что после настройки набора тестов любое изменение кода становится простым делом. Запустите Pester и просмотрите результаты., что защищает вас от неудач в крупных, действующих проектах.

PowerShell, модули и Pester в конвейерах CI/CD

Сегодня интеграция PowerShell и Pester в компьютерные системы стала очень распространенной практикой. конвейеры непрерывной интеграции и доставки, например, с использованием GitHub Actions.В средах выполнения, размещенных на GitHub, уже предустановлены PowerShell 7 и Pester, а также есть возможность установить дополнительные модули из Галереи. Установить модуль.

Типичный рабочий процесс начинается с тестового задания, которое при каждом обновлении... Запустите Pester для вашего модуля.Упрощенный пример в формате YAML может включать такие шаги, как:

  • Извлечение репозитория (actions/checkout@v5).
  • Проведение простого теста с Test-Path resultsfile.log | Should -Be $true для проверки того, что результат получен.
  • Запуск полного тестового файла с Invoke-Pester Unit.Tests.ps1 -Passthru.

Помимо запуска Pester, это также распространенная практика. Установите зависимости из Галереи. (например, SqlServer o PSScriptAnalyzer), настройте репозиторий PSGallery как доверенный и кэшировать модули ускоряться загрузок использование действия/кэшВ Linux, например, типичный кэш модулей расположен в ~/.local/share/powershell/ModulesВ Windows же путь меняется.

Ещё один очень полезный шаблон — это использование PSScriptAnalyzer находится в процессе разработки для проверки всех файлов .ps1.Это генерирует список проблем по степени серьезности и прерывает выполнение задания при обнаружении серьезных ошибок. Это вынуждает вас проводить техническое обслуживание. Последовательный стиль кодирования без очевидных ошибок. еще до того, как перейти к функциональному тестированию с помощью Pester.

Публикация модулей в PowerShell Gallery из системы непрерывной интеграции (CI).

После того, как ваши тесты Pester в CI пройдут успешно, логичным следующим шагом будет... Автоматизируйте публикацию вашего модуля в Галерее. При создании нового релиза. В GitHub Actions это обычно делается с помощью рабочего процесса, который запускается событиями определенного типа. релиз: создан.

El соответствующая работа обычно:

  • Посмотрите код.
  • Запустите скрипт сборки (например) ./build.ps1 -Path /tmp/samplemodule), которая генерирует окончательную структуру модуля, включая файлы .psm1, .psd1 и любые дополнительные ресурсы.
  • Прочитайте секрет NUGET_KEY Раскрыть секреты репозитория и предоставить к ним доступ в виде переменной окружения.
  • Позвонить Publish-Module -Path /tmp/samplemodule -NuGetApiKey $env:NUGET_KEY -Verbose чтобы загрузить новую версию в Галерею.

В этом потоке Секреты издательского дела никогда не записываются в открытом виде в скриптах.Они управляются исключительно поставщиком CI, и модуль публикуется только в том случае, если Тесты Пестера ранее были пройдены успешно.Это самый простой способ избежать проблем с "неработоспособными" версиями для последующих пользователей.

В качестве завершающего штриха обычно добавляют еще один шаг для загрузите тестовые артефакты производится Invoke-Pester (например, XML-файл или CliXml с результатами) с использованием действия загрузка-артефактаЭто позволяет проанализировать причины сбоя, даже если задание помечено как неудачное, благодаря таким условиям, как... if: ${{ always() }} которые гарантируют загрузку, даже если Pester вернет ошибки.

В итоге, объедините Хорошо структурированные модули PowerShell, всестороннее тестирование с помощью Pester и конвейеры CI/CD, которые автоматически запускаются, анализируются и публикуются. Это позволяет перейти от ненадежных и уязвимых скриптов к экосистеме многократно используемых, версионированных и надежных инструментов, что делает повседневную работу намного комфортнее и предсказуемее.