Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: Add integration-tests for Invoke-AzSqlDatabaseMigration #232

Merged
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
f29f458
Integration Test: test if migrations are successfully executed
fgheysels Oct 19, 2021
fa69b13
Fix syntax error in test migration script
fgheysels Oct 19, 2021
0e1b9d6
Add test for executing migration scripts
fgheysels Oct 19, 2021
8b8bc7d
Integration test: old migration-scripts are still supported
fgheysels Oct 19, 2021
21432c9
Improvement: add reason on asserts
fgheysels Oct 19, 2021
3a8f50f
Integration test: migration stops on error
fgheysels Oct 19, 2021
a7fa966
Try to open/warm the SQL db
fgheysels Oct 24, 2021
6680aa3
Write informational messages
fgheysels Oct 24, 2021
4ced729
Specify connection-timeout
fgheysels Oct 24, 2021
61feaf0
Remove unnecessary code
fgheysels Oct 24, 2021
d013905
multiple contexts
fgheysels Oct 26, 2021
d65139b
lowercase bools
fgheysels Oct 26, 2021
790fcd3
Improve versionnr check
fgheysels Oct 26, 2021
1afdbc2
comment improvement
fgheysels Oct 26, 2021
97d7c98
Improved test-cleanup
fgheysels Oct 26, 2021
1784960
drop table before drop schema
fgheysels Oct 26, 2021
bc144ec
Fine tune sql statement
fgheysels Oct 26, 2021
17a4f7c
make sure schema is dropped
fgheysels Oct 26, 2021
72c92bb
drop correct table
fgheysels Oct 26, 2021
5b07885
Update src/Arcus.Scripting.Tests.Integration/Arcus.Scripting.Sql.test…
fgheysels Oct 28, 2021
5c28e52
Update src/Arcus.Scripting.Tests.Integration/Arcus.Scripting.Sql.test…
fgheysels Oct 28, 2021
9c65f3b
comments
fgheysels Oct 28, 2021
a78381c
Fix comment
fgheysels Oct 28, 2021
8d7b044
rename refactor
fgheysels Oct 28, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ for ($i = 0; $i -lt $files.Count; $i++) {
$migrationDescription = $migrationDescription.Substring(0, 256)
}

$updateVersionQuery = "INSERT INTO [$DatabaseSchema].[DatabaseVersion] ([MajorVersionNumber], [MinorVersionNumber], [PatchVersionNumber], [MigrationDescription], [MigrationDate]) " +
"SELECT $($scriptVersionNumber.MajorVersionNumber), $($scriptVersionNumber.MinorVersionNumber), $($scriptVersionNumber.PatchVersionNumber), '$migrationDescription', getdate()"
$updateVersionQuery = "INSERT INTO [$DatabaseSchema].[DatabaseVersion] ([MajorVersionNumber], [MinorVersionNumber], [PatchVersionNumber], [MigrationDescription], [MigrationDate]) " +
"SELECT $($scriptVersionNumber.MajorVersionNumber), $($scriptVersionNumber.MinorVersionNumber), $($scriptVersionNumber.PatchVersionNumber), '$migrationDescription', getdate()"

Execute-DbCommand $params $updateVersionQuery

Expand Down
232 changes: 212 additions & 20 deletions src/Arcus.Scripting.Tests.Integration/Arcus.Scripting.Sql.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,54 +2,108 @@ Import-Module SqlServer
Import-Module -Name $PSScriptRoot\..\Arcus.Scripting.Sql -ErrorAction Stop

function global:Run-AzSqlCommand ($params, $command) {
Invoke-Sqlcmd @params -Query $command -Verbose -QueryTimeout 180 -ErrorAction Stop -ErrorVariable err
Invoke-Sqlcmd @params -Query $command -Verbose -QueryTimeout 180 -ConnectionTimeout 60 -ErrorAction Stop -ErrorVariable err
if ($err) {
throw ($err)
}
}

function global:Run-AzSqlQuery ($params, $query) {
$result = Invoke-Sqlcmd @params -Query $query -Verbose -ErrorAction Stop -ErrorVariable err
$result = Invoke-Sqlcmd @params -Query $query -Verbose -ConnectionTimeout 60 -ErrorAction Stop -ErrorVariable err
if ($err) {
throw ($err)
}
return $result
}

function global:Drop-AzSqlDatabaseTable ($params, $databaseTable, $schema = "dbo") {
Run-AzSqlCommand $params "DROP TABLE [$schema].[$databaseTable]"
Run-AzSqlCommand $params "DROP TABLE IF EXISTS [$schema].[$databaseTable]"
stijnmoreels marked this conversation as resolved.
Show resolved Hide resolved
}

function global:Get-AzSqlDatabaseVersion ($params, $schema = "dbo") {
$row = Run-AzSqlQuery $params "SELECT TOP 1 MajorVersionNumber, MinorVersionNumber, PatchVersionNumber FROM [$schema].[DatabaseVersion] ORDER BY MajorVersionNumber DESC, MinorVersionNumber DESC, PatchVersionNumber DESC"

$version = [DatabaseVersion]::new()
if ($row -ne $row) {
if (($null -ne $row) -and ($null -ne $row.ItemArray) -and ($row.ItemArray.Length -ge 3) ) {
$version = [DatabaseVersion]::new(
[convert]::ToInt32($databaseVersionNumberDataRow.ItemArray[0]),
[convert]::ToInt32($databaseVersionNumberDataRow.ItemArray[1]),
[convert]::ToInt32($databaseVersionNumberDataRow.ItemArray[2]))
[convert]::ToInt32($row.ItemArray[0]),
[convert]::ToInt32($row.ItemArray[1]),
[convert]::ToInt32($row.ItemArray[2]))
}

return $version
}

function global:VerifyDatabaseVersionRow ($row, $expectedMajorVersion, $expectedMinorVersion, $expectedPatchVersion) {
[convert]::ToInt32($row.ItemArray[0]) | Should -Be $expectedMajorVersion
[convert]::ToInt32($row.ItemArray[1]) | Should -Be $expectedMinorVersion
[convert]::ToInt32($row.ItemArray[2]) | Should -Be $expectedPatchVersion
}

function global:Create-MigrationTable ($params) {
$createTable = "CREATE TABLE dbo.[DatabaseVersion] " +
"( " +
" [MajorVersionNumber] INT NOT NULL, " +
" [MinorVersionNumber] INT NOT NULL, " +
" [PatchVersionNumber] INT NOT NULL, " +
" [MigrationDescription] [nvarchar](256) NOT NULL, " +
" [MigrationDate] DATETIME NOT NULL " +
" CONSTRAINT [PK_DatabaseVersion] PRIMARY KEY CLUSTERED ([MajorVersionNumber],[MinorVersionNumber],[PatchVersionNumber]) " +
" WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) " +
")"

Run-AzSqlCommand $params $createTable
}

function global:TableExists($params, $tableName) {
$result = Run-AzSqlQuery $params "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '$tableName' AND TABLE_CATALOG = '$($params.Database)'"

if ($result.ItemArray[0] -eq 1) {
return $True
}

return $False
}

function global:ColumnExists($params, $tableName, $columnName) {
$result = Run-AzSqlQuery $params "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '$tableName' AND COLUMN_NAME = '$columnName'"

if ($result.ItemArray[0] -eq 1) {
return $True
}

return $False
fgheysels marked this conversation as resolved.
Show resolved Hide resolved
}


InModuleScope Arcus.Scripting.Sql {
Describe "Arcus Azure SQL integration tests" {
BeforeEach {
BeforeAll {

$filePath = "$PSScriptRoot\appsettings.json"
[string]$appsettings = Get-Content $filePath
$config = ConvertFrom-Json $appsettings
$params = @{
'ServerInstance' = $config.Arcus.Sql.ServerName
'Database' = $config.Arcus.Sql.DatabaseName
'Username' = $config.Arcus.Sql.UserName
'Password' = $config.Arcus.Sql.Password
'OutputSqlErrors' = $true
'AbortOnError' = $true
'ServerInstance' = $config.Arcus.Sql.ServerName
'Database' = $config.Arcus.Sql.DatabaseName
'Username' = $config.Arcus.Sql.UserName
'Password' = $config.Arcus.Sql.Password
'OutputSqlErrors' = $true
'AbortOnError' = $true
}

& $PSScriptRoot\Connect-AzAccountFromConfig.ps1 -config $config

# Try to open a connection to the SQL database, so that the
# Azure Database that can be paused, is starting up. This should
# avoid having timeout errors during the test themselves.
try {
Write-Host "Execute dummy SQL statement to make sure the Azure SQL DB is resumed."
Invoke-Sqlcmd @params -Query "SELECT TOP 1 FROM INFORMATION_SCHEMA.TABLES" -ConnectionTimeout 60 -Verbose
}
catch {
# We don't care if an exception is thrown; we just want to 'activate' the Azure SQL database
}
}
Context "DatabaseVersion table" {
It "Invoke first SQL migration on empty database creates new DatabaseVersion table" {
Expand All @@ -67,10 +121,11 @@ InModuleScope Arcus.Scripting.Sql {

# Assert
$version = Get-AzSqlDatabaseVersion $params
$version.MajorVersionNumber | Should -Be 0
$version.MajorVersionNumber | Should -Be 1
$version.MinorVersionNumber | Should -Be 0
$version.PatchVersionNumber | Should -Be 0
} finally {
}
finally {
Drop-AzSqlDatabaseTable $params "DatabaseVersion"
}
}
Expand All @@ -92,10 +147,11 @@ InModuleScope Arcus.Scripting.Sql {

# Assert
$version = Get-AzSqlDatabaseVersion $params $customSchema
$version.MajorVersionNumber | Should -Be 0
$version.MajorVersionNumber | Should -Be 1
$version.MinorVersionNumber | Should -Be 0
$version.PatchVersionNumber | Should -Be 0
} finally {
}
finally {
Drop-AzSqlDatabaseTable $params "DatabaseVersion" $customSchema
Run-AzSqlCommand $params "DROP SCHEMA $customSchema"
}
Expand Down Expand Up @@ -133,11 +189,147 @@ InModuleScope Arcus.Scripting.Sql {
$result.ItemArray[0] | Should -Be 0

$version = Get-AzSqlDatabaseVersion $params
$version.MajorVersionNumber | Should -Be 0
$version.MajorVersionNumber | Should -Be 1
$version.MinorVersionNumber | Should -Be 0
$version.PatchVersionNumber | Should -Be 0
}
finally {
Drop-AzSqlDatabaseTable $params "DatabaseVersion"
}
}
It "Migration scripts are correctly executed" {
fgheysels marked this conversation as resolved.
Show resolved Hide resolved
# Arrange: Create the DatabaseVersion table and pre-populate it
Create-MigrationTable $params

$addBaselineRecord = "INSERT INTO [DatabaseVersion] ([MajorVersionNumber], [MinorVersionNumber], [PatchVersionNumber], [MigrationDescription], [MigrationDate]) SELECT 0, 0, 1, 'Baseline', getdate()"

Run-AzSqlCommand $params $addBaselineRecord

try {
# Act: execute the specified migration-scripts
Invoke-AzSqlDatabaseMigration `
-ServerName $config.Arcus.Sql.ServerName `
-DatabaseName $config.Arcus.Sql.DatabaseName `
-Username $config.Arcus.Sql.Username `
-Password $config.Arcus.Sql.Password `
-ScriptsFolder "$PSScriptRoot\SqlScripts\MigrationScriptsAreSuccessfullyExecuted"

# Assert
# The 'NonExistingTable' should not exist, as we already had a record in DatabaseVersion for 0.0.1, so that
fgheysels marked this conversation as resolved.
Show resolved Hide resolved
# migration script should not have been executed.
$result = TableExists $params 'NonExistingTable'
$result | Should -Be $False -Because 'DatabaseVersion was initialized with version that introduced this table, so script should not have been executed'

# The 'Customer' table should not exist, as it should have been renamed by one of the migrationscripts
$result = TableExists $params 'Customer'
$result | Should -Be $False -Because 'Customer table should have been renamed'

# The Customer table was renamed to Person
$result = TableExists $params 'Person'
$result | Should -Be $True -Because 'migration-script renamed Customer table to Person table'

$result = ColumnExists $params 'Person' 'Address'
$result | Should -Be $True -Because 'Migration script added additional Address column to table'
fgheysels marked this conversation as resolved.
Show resolved Hide resolved

$version = Get-AzSqlDatabaseVersion $params
$version.MajorVersionNumber | Should -Be 1
$version.MinorVersionNumber | Should -Be 0
$version.PatchVersionNumber | Should -Be 0
} finally {
}
finally {
Drop-AzSqlDatabaseTable $params "DatabaseVersion"
Drop-AzSqlDatabaseTable $params "Person"
Drop-AzSqlDatabaseTable $params "Customer"
}
}
It "Old script naming convention is still supported" {
try {
# Act and arrange: execute the specified migration-scripts
fgheysels marked this conversation as resolved.
Show resolved Hide resolved
Invoke-AzSqlDatabaseMigration `
-ServerName $config.Arcus.Sql.ServerName `
-DatabaseName $config.Arcus.Sql.DatabaseName `
-Username $config.Arcus.Sql.Username `
-Password $config.Arcus.Sql.Password `
-ScriptsFolder "$PSScriptRoot\SqlScripts\OldMigrationScriptsAreStillSupported"

$version = Get-AzSqlDatabaseVersion $params
$version.MajorVersionNumber | Should -Be 2 -Because "latest migration-script has version number 2"
$version.MinorVersionNumber | Should -Be 0 -Because "Old migration scripts are used that do not have a minor version number"
$version.PatchVersionNumber | Should -Be 0 -Because "Old migration scripts are used that do not have a patch version number"
fgheysels marked this conversation as resolved.
Show resolved Hide resolved
}
finally {
Drop-AzSqlDatabaseTable $params "DatabaseVersion"
}
}
It "Combination of old and new migration-script naming convention is supported" {
fgheysels marked this conversation as resolved.
Show resolved Hide resolved
try {
# Act and arrange: execute the specified migration-scripts
Invoke-AzSqlDatabaseMigration `
-ServerName $config.Arcus.Sql.ServerName `
-DatabaseName $config.Arcus.Sql.DatabaseName `
-Username $config.Arcus.Sql.Username `
-Password $config.Arcus.Sql.Password `
-ScriptsFolder "$PSScriptRoot\SqlScripts\OldAndNewNamingConventionSupported"

$version = Get-AzSqlDatabaseVersion $params
$version.MajorVersionNumber | Should -Be 3 -Because "latest migration-script has version number 3"
$version.MinorVersionNumber | Should -Be 0
$version.PatchVersionNumber | Should -Be 0

$versions = Run-AzSqlQuery $params "SELECT MajorVersionNumber, MinorVersionNumber, PatchVersionNumber FROM DatabaseVersion ORDER BY MigrationDate ASC"

$versions.Length | Should -Be 6

for ($i = 0; $i -lt $versions.Length; $i++) {

switch ($i) {
0 {
VerifyDatabaseVersionRow $versions[$i] 0 0 1
}
1 {
VerifyDatabaseVersionRow $versions[$i] 1 0 0
}
2 {
VerifyDatabaseVersionRow $versions[$i] 2 0 0
}
3 {
VerifyDatabaseVersionRow $versions[$i] 2 0 1
}
4 {
VerifyDatabaseVersionRow $versions[$i] 2 1 0
}
5 {
VerifyDatabaseVersionRow $versions[$i] 3 0 0
}
}
}
stijnmoreels marked this conversation as resolved.
Show resolved Hide resolved
}
finally {
Drop-AzSqlDatabaseTable $params "DatabaseVersion"
Drop-AzSqlDatabaseTable $params "Person"
Drop-AzSqlDatabaseTable $params "Customer"
fgheysels marked this conversation as resolved.
Show resolved Hide resolved
}
}
It "Migration Stops on Error" {
try {
# Act and arrange: execute the specified migration-scripts
Invoke-AzSqlDatabaseMigration `
-ServerName $config.Arcus.Sql.ServerName `
-DatabaseName $config.Arcus.Sql.DatabaseName `
-Username $config.Arcus.Sql.Username `
-Password $config.Arcus.Sql.Password `
-ScriptsFolder "$PSScriptRoot\SqlScripts\MigrationStopsOnError"
}
catch {
Write-Host "Expected migration error occured"
}
finally {
$version = Get-AzSqlDatabaseVersion $params
$version.MajorVersionNumber | Should -Be 1 -Because "latest successfull migration-script has major version number 1"
$version.MinorVersionNumber | Should -Be 0 -Because "latest successfull migration-script has major version number 0"
$version.PatchVersionNumber | Should -Be 0 -Because "latest successfull migration-script has major version number 0"
stijnmoreels marked this conversation as resolved.
Show resolved Hide resolved

Drop-AzSqlDatabaseTable $params "DatabaseVersion"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CREATE TABLE NonExistingTable
(
[Id] INT,
[Description] NVARCHAR(20)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CREATE TABLE [Customer]
(
[Id] INT,
[Name] NVARCHAR(20)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE [Customer]
ADD [Address] NVARCHAR(255)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sp_rename [Customer], [Person]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT * FROM INFORMATION_SCHEMA.TABLES
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT * FROM NonExistingTable
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CREATE TABLE [Person]
(
[Id] INT,
[Name] VARCHAR(50)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sp_rename 'Person', 'Customer'
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
INSERT INTO [Customer]
([Id], [Name], [Address])
VALUES
(1, 'Name', 'Street')
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE [Customer]
ALTER COLUMN [Address] VARCHAR(250) NOT NULL
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE Customer
ADD [Address] VARCHAR(250)
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE [Customer]
DROP COLUMN [Address]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT * FROM INFORMATION_SCHEMA.TABLES
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT * FROM INFORMATION_SCHEMA.TABLES