Database
 sql >> Teknologi Basis Data >  >> RDS >> Database

Langsung ke Memulai Pengembangan Basis Data Berbasis Tes (TDDD)

Sebagai aturan, kami mulai mengembangkan solusi basis data dengan membuat objek basis data, seperti tabel, tampilan, prosedur tersimpan, dll., berdasarkan kebutuhan bisnis. Pendekatan ini juga dikenal sebagai Pengembangan Basis Data Konvensional . Dalam artikel ini, kita akan mengeksplorasi pendekatan ini dan mengilustrasikannya dengan contoh.

Pengembangan Basis Data Konvensional

Gaya pengembangan terdiri dari langkah-langkah berikut:

  1. Terima persyaratannya
  2. Membuat objek database berdasarkan kebutuhan
  3. Jalankan pengujian unit untuk objek database untuk melihat apakah mereka memenuhi persyaratan
  4. Terima persyaratan baru
  5. Ubah objek database yang ada atau tambahkan yang baru untuk memenuhi persyaratan baru
  6. Buat dan jalankan pengujian unit untuk memeriksa apakah persyaratan baru berfungsi sesuai dan tidak bertentangan dengan yang sebelumnya

Untuk menjelajahi dan mengilustrasikan prosesnya, mari kita mulai dengan menyiapkan contoh database SQLDevBlog :

  
-- Create sample database (SQLDevBlog)
  CREATE DATABASE SQLDevBlog
 

Gunakan kode berikut untuk membuat tabel dalam database sampel tersebut:

USE SQLDevBlog;

-- (1) Create Author table in the sample database
CREATE TABLE Author (
  AuthorId INT PRIMARY KEY IDENTITY (1, 1)
 ,Name VARCHAR(40)
 ,RegistrationDate DATETIME2
 ,Notes VARCHAR(400)
)

-- (2) Create Article Category table in the sample database
CREATE TABLE Category (
  CategoryId INT PRIMARY KEY IDENTITY (1, 1)
 ,Name VARCHAR(50)
 ,Notes VARCHAR(400)
)

-- (3) Create Article table in the sample database
CREATE TABLE Article (
  ArticleId INT PRIMARY KEY IDENTITY (1, 1)
 ,CategoryId INT
 ,AuthorId INT
 ,Title VARCHAR(150)
 ,Published DATETIME2
 ,Notes VARCHAR(400)  
)

-- Adding foreign keys for author and article category
ALTER TABLE Article ADD CONSTRAINT FK_Category_CategoryId FOREIGN KEY (CategoryId) REFERENCES Category (CategoryId)
ALTER TABLE Article ADD CONSTRAINT FK_Author_AuthorId FOREIGN KEY (AuthorId) REFERENCES Author (AuthorId)

GO
 

Tinjau diagram database dengan tabel yang baru dibuat:

Catatan :Saya menggunakan di sini dbForge Studio untuk SQL Server untuk melakukan semua tugas. Tampilan outputnya mungkin berbeda dengan SSMS (SQL Server Management Studio), tetapi hasilnya sama.

Selanjutnya, kita akan mengisi SQLDevBlog our contoh database untuk membuat skenario yang lebih realistis:

-- (5) Populating Author table
INSERT INTO Author (Name, RegistrationDate, Notes)
  VALUES ('Sam', '2017-01-01', 'Database Analyst'),
  ('Asif', '2017-01-02', 'Database and Business Intelligence Developer'),
  ('Sadaf', '2018-01-01', 'Database Analyst Programmer')

-- (6) Populating Category table
INSERT INTO Category (Name, Notes)
  VALUES ('Development', 'Articles about database development'),
  ('Testing', 'Database testing related articles'),
  ('DLM', 'Database lifecycle management')

-- (7) Populating Article 
INSERT INTO Article (CategoryId, AuthorId, Title, Published, Notes)
  VALUES (1, 1, 'Fundamentals of SQL Database Development', '02-01-2018', ''),
  (1, 2, 'Advanced Database Development', '02-01-2018', ''),
  (2, 3, 'All About Database Testing', '03-01-2018', '');
GO
 

Hasilnya, kami memiliki tabel yang diisi berikut ini:

Sekarang setelah kita selesai dengan pengaturan database dan populasi tabel, kita menghadapi langkah berikutnya. Kita harus meniru skenario dengan persyaratan baru.

Persyaratan untuk Menambahkan Kategori Baru

Persyaratan baru menyatakan bahwa administrator harus dapat menambahkan kategori baru ke daftar kategori yang tersedia . Untuk memenuhi persyaratan ini, tim pengembangan Anda harus membuat prosedur tersimpan untuk menambahkan persyaratan baru dengan mudah. Atau, kita harus membuat AddCategory Objek Basis Data.

Untuk membuat prosedur tersimpan, jalankan skrip berikut:

-- (8) This procedure meets a new requirement by adding a new category
CREATE PROCEDURE dbo.AddCategory @CategoryName VARCHAR(50),
@Notes VARCHAR(400)
AS
  INSERT INTO Category (Name, Notes)
    VALUES (@CategoryName, @Notes);
GO
 

Hasilnya adalah sebagai berikut:

Buat Uji Unit Basis Data untuk Memeriksa apakah Prosedur Bekerja dengan Benar

Langkah selanjutnya adalah membuat pengujian unit database untuk memeriksa apakah prosedur tersimpan memenuhi spesifikasi.

Tip ini berfungsi untuk dbForge Studio untuk SQL Server (atau hanya Uji Unit dbForge ) dan SSMS (SQL Server Management Studio) . Catatan:Saat menggunakan SSMS (SQL Server Management Studio), pastikan untuk menginstal tSQLt Kerangka kerja untuk menulis pengujian unit.

Untuk membuat pengujian unit database pertama, klik kanan SQLDevBlog database> Uji Unit > Tambahkan Tes Baru

Tambahkan Tes Baru jendela terbuka. Isi semua informasi yang diperlukan dan klik Tambahkan Tes .

Buat unit test sebagai berikut dan simpan:

--  Comments here are associated with the test.
--  For test case examples, see: http://tsqlt.org/user-guide/tsqlt-tutorial/
CREATE PROCEDURE AddCategoryTests.[test to check if AddCategory procedure works]
AS
BEGIN
  --Assemble
  EXEC tSQLt.FakeTable @TableName = 'dbo.Category' -- create an empty dependency free Category table
                    

  
  CREATE TABLE AddCategoryTests.Expected ( -- create expected table 
  CategoryId INT 
 ,Name VARCHAR(50) NULL
 ,Notes VARCHAR(400) NULL
  ) 
                      
  INSERT INTO AddCategoryTests.Expected (CategoryId,Name, Notes) -- Insert data into expected table
  VALUES (null,'Database Dummy Category', 'This is just a dummy category for testing');
  
  --Act
  EXEC AddCategory @CategoryName = 'Database Dummy Category' 
                  ,@Notes = 'This is just a dummay category for testing'

   
  --Assert
  EXEC tSQLt.AssertEqualsTable @Expected = 'AddCategoryTests.Expected'
                              ,@Actual = 'dbo.Category'
                           

END;
GO
 

Klik Database menu> Uji Unit > Lihat Daftar Tes dan jalankan unit test seperti yang ditunjukkan di bawah ini:

Kita dapat melihat bahwa unit test berhasil. Dengan demikian, kategori baru dapat ditambahkan ke database (tabel). Persyaratan telah dipenuhi.

Sekarang, kita akan menjelajahi pengembangan database yang digerakkan oleh pengujian dan menjelaskan bagaimana proses penulisan pengujian unit dapat memenuhi persyaratan.

Pengembangan Basis Data Berbasis Uji (TDDD)

Pengembangan basis data berbasis pengujian (TDDD) dimulai dengan menulis pengujian unit yang akan gagal terlebih dahulu. Kemudian, kami akan memodifikasinya untuk lulus, dan kemudian memperbaikinya.

Pengujian unit ditulis untuk memenuhi persyaratan dan pengujian unit yang memerlukan objek database untuk dibuat dan dijalankan dengan benar.

Untuk memahami perbedaan antara pengembangan database tradisional dan pengembangan database berbasis pengujian, mari kita buat SQLDevBlogTDD basis data. Ini sama dengan SQLDevBlog .

-- Create sample database (SQLDevBlogTDD)
  CREATE DATABASE SQLDevBlogTDD
 

Kemudian, isi database sampel dengan tabel:

USE SQLDevBlogTDD;

-- (1) Create Author table in the sample database
CREATE TABLE Author (
  AuthorId INT PRIMARY KEY IDENTITY (1, 1)
 ,Name VARCHAR(40)
 ,RegistrationDate DATETIME2
 ,Notes VARCHAR(400)
)

-- (2) Create Article Category table in the sample database
CREATE TABLE Category (
  CategoryId INT PRIMARY KEY IDENTITY (1, 1)
 ,Name VARCHAR(50)
 ,Notes VARCHAR(400)
)

-- (3) Create Article table in the sample database
CREATE TABLE Article (
  ArticleId INT PRIMARY KEY IDENTITY (1, 1)
 ,CategoryId INT
 ,AuthorId INT
 ,Title VARCHAR(150)
 ,Published DATETIME2
 ,Notes VARCHAR(400)  
)

-- Adding foreign keys for author and article category
ALTER TABLE Article ADD CONSTRAINT FK_Category_CategoryId FOREIGN KEY (CategoryId) REFERENCES Category (CategoryId)
ALTER TABLE Article ADD CONSTRAINT FK_Author_AuthorId FOREIGN KEY (AuthorId) REFERENCES Author (AuthorId)

GO
 

Kita harus mengisi database sampel kita untuk membuat skenario yang lebih realistis sebagai berikut:

-- Use SQLDevBlogTDD
-- (5) Populating Author table
INSERT INTO Author (Name, RegistrationDate, Notes)
  VALUES ('Sam', '2017-01-01', 'Database Analyst'),
  ('Asif', '2017-01-02', 'Database and Business Intelligence Developer'),
  ('Sadaf', '2018-01-01', 'Database Analyst Programmer')

-- (6) Populating Category table
INSERT INTO Category (Name, Notes)
  VALUES ('Development', 'Articles about database development'),
  ('Testing', 'Database testing related articles'),
  ('DLM', 'Database lifecycle management')

-- (7) Populating Article 
INSERT INTO Article (CategoryId, AuthorId, Title, Published, Notes)
  VALUES (1, 1, 'Fundamentals of SQL Database Development', '02-01-2018', ''),
  (1, 2, 'Advanced Database Development', '02-01-2018', ''),
  (2, 3, 'All About Database Testing', '03-01-2018', '');
GO
 

Persyaratan untuk Menambahkan Kategori Baru (TDDD)

Sekarang, kami memiliki persyaratan yang sama:administrator harus dapat menambahkan kategori baru ke daftar kategori yang tersedia. Untuk memenuhi persyaratan, pertama-tama kita perlu menulis pengujian unit basis data yang mencari objek potensial.

Begitulah cara kerja TDDD:unit test pertama gagal karena kita berasumsi bahwa kita sedang mencari objek yang saat ini tidak ada, tetapi akan segera ada.

Buat dan Jalankan Pengujian Unit Basis Data untuk Memeriksa Keberadaan Objek yang Diinginkan

Meskipun kami tahu bahwa itu tidak ada sekarang, kami menganggap ini sebagai titik awal.

Di dbForge Studio untuk SQL Server, pengujian unit database yang mendukung TDDD secara default dibuat untuk gagal terlebih dahulu. Kemudian, kita akan mengubahnya sedikit. Jika Anda menggunakan tSQLt kerangka kerja pengujian unit basis data secara langsung, tulis pengujian unit berikut:

--  Comments here are associated with the test.
--  For test case examples, see: http://tsqlt.org/user-guide/tsqlt-tutorial/
CREATE PROCEDURE CategoryTests.[test to check if routine to add new category exists]
AS
BEGIN
  --Assemble
  --  This section is for code that sets up the environment. It often
  --  contains calls to methods such as tSQLt.FakeTable and tSQLt.SpyProcedure
  --  along with INSERTs of relevant data.
  --  For more information, see http://tsqlt.org/user-guide/isolating-dependencies/

  --Act
  --  Execute the code under tests like a stored procedure, function, or view
  --  and capture the results in variables or tables.

  --Assert
  --  Compare the expected and actual values, or call tSQLt.Fail in an IF statement.
  --  Available Asserts: tSQLt.AssertEquals, tSQLt.AssertEqualsString, tSQLt.AssertEqualsTable
  --  For a complete list, see: http://tsqlt.org/user-guide/assertions/
  EXEC tSQLt.AssertObjectExists @ObjectName = N'dbo.AddCategory'
                              

END;
GO
 

Setelah Anda menjalankan pengujian unit basis data, Anda dapat melihat bahwa pengujian tersebut gagal:

Buat Objek Basis Data dan Jalankan Ulang Uji Unit

Langkah selanjutnya adalah membuat objek database yang dibutuhkan. Dalam kasus kami, ini adalah prosedur tersimpan.

-- (8) This procedure meets the new requirement by adding a new category
CREATE PROCEDURE dbo.AddCategory @CategoryName VARCHAR(50),
@Notes VARCHAR(400)
AS  
-- Category Procedure Stub (template) in TDDD
GO
 

Jalankan unit test lagi – kali ini berhasil:

Tetapi tidak cukup untuk lulus pengujian unit jika prosedur tersimpan ada. Kami juga perlu memeriksa apakah prosedur tersimpan menambahkan kategori baru.

Buat Pengujian Unit Basis Data untuk Memeriksa apakah Rutinitas Berfungsi dengan Baik

Mari buat pengujian unit basis data baru:

--  Comments here are associated with the test.
--  For test case examples, see: http://tsqlt.org/user-guide/tsqlt-tutorial/
CREATE PROCEDURE CategoryTests.[test to check routine adds new category]
AS
BEGIN
  --Assemble
  EXEC tSQLt.FakeTable @TableName = 'dbo.Category' -- create an empty dependency free Category table
                      

  
  CREATE TABLE CategoryTests.Expected ( -- create expected table 
  CategoryId INT 
 ,Name VARCHAR(50) NULL
 ,Notes VARCHAR(400) NULL
  ) 
                      
  INSERT INTO CategoryTests.Expected (CategoryId,Name, Notes) -- Insert data into expected table
  VALUES (null,'Database Dummy Category', 'This is just a dummy category for testing');
  
  --Act
  EXEC AddCategory @CategoryName = 'Database Dummy Category' 
                  ,@Notes = 'This is just a dummay category for testing'

  --SELECT * INTO CategoryTests.Actual FROM Category -- put category table data into an actual table
  
  --Assert
  EXEC tSQLt.AssertEqualsTable @Expected = 'CategoryTests.Expected'
                              ,@Actual = 'dbo.Category'
                           

END;
GO
 

Seperti yang Anda lihat, unit test gagal untuk pertama kalinya dan berhasil untuk kedua kalinya:

Tambahkan Fungsionalitas ke Rutin dan Jalankan Ulang Unit Test

Ubah prosedur tersimpan dengan menambahkan fungsionalitas yang diperlukan sehingga pengujian dapat berhasil seperti yang ditunjukkan di bawah ini:

-- (8) This procedure meets the new requirement by adding a new category
ALTER PROCEDURE dbo.AddCategory @CategoryName VARCHAR(50),
@Notes VARCHAR(400)
AS
  INSERT INTO Category (Name, Notes)
    VALUES (@CategoryName, @Notes);
GO
 

Jalankan kembali pengujian unit untuk memeriksa apakah semuanya berhasil termasuk prosedur tersimpan yang baru saja dimodifikasi:

Dengan cara ini, kami telah berhasil mengimplementasikan pengembangan basis data yang digerakkan oleh pengujian. Sekarang kita bisa fokus pada persyaratan saja. Tes unit merangkum persyaratan sehingga menuntut objek database untuk dibuat dan dijalankan dengan benar untuk memenuhi spesifikasi.

Mari kita lihat seberapa efektif TDDD dalam memenuhi persyaratan pelaporan bisnis.

Memenuhi Persyaratan Pelaporan Bisnis melalui TDDD

Kami menganggap database sudah mendapatkan objek yang diperlukan (seperti tabel) sebelum menerima persyaratan pelaporan bisnis baru.

Mari kita buat database sampel bernama SQLDevBlogReportTDD :

-- Create sample database (SQLDevBlogReportTDD)
CREATE DATABASE SQLDevBlogReportTDD;
GO
 

Kemudian buat dan isi tabel untuk database sampel menggunakan kode berikut:

USE SQLDevBlogReportTDD;
-- (1) Create Author table in the sample database
CREATE TABLE Author (
  AuthorId INT PRIMARY KEY IDENTITY (1, 1)
 ,Name VARCHAR(40)
 ,RegistrationDate DATETIME2
 ,Notes VARCHAR(400)
)

-- (2) Create an Article Category table in the sample database
CREATE TABLE Category (
  CategoryId INT PRIMARY KEY IDENTITY (1, 1)
 ,Name VARCHAR(50)
 ,Notes VARCHAR(400)
)

-- (3) Create Article table in the sample database
CREATE TABLE Article (
  ArticleId INT PRIMARY KEY IDENTITY (1, 1)
 ,CategoryId INT
 ,AuthorId INT
 ,Title VARCHAR(150)
 ,Published DATETIME2
 ,Notes VARCHAR(400)  
)

-- Adding foreign keys for author and article category
ALTER TABLE Article ADD CONSTRAINT FK_Category_CategoryId FOREIGN KEY (CategoryId) REFERENCES Category (CategoryId)
ALTER TABLE Article ADD CONSTRAINT FK_Author_AuthorId FOREIGN KEY (AuthorId) REFERENCES Author (AuthorId)

GO

-- (4) Populating Author table
INSERT INTO Author (Name, RegistrationDate, Notes)
  VALUES ('Peter', '2017-01-01', 'Database Analyst'),
  ('Adil', '2017-01-02', 'Database and Business Intelligence Developer'),
  ('Sarah', '2018-01-01', 'Database Analyst Programmer'),
  ('Asim', '2018-01-01', 'Database Analyst')

-- (5) Populating Category table
INSERT INTO Category (Name, Notes)
  VALUES 
  ('Analysis', 'Database Analysis'),
  ('Development', 'Articles about database development'),
  ('Testing', 'Database testing related articles'),
  ('DLM', 'Database lifecycle management')
 

-- (6) Populating Article 
INSERT INTO Article (CategoryId, AuthorId, Title, Published, Notes)
  VALUES (1, 1, 'Replicating a problem in SQL', '02-01-2018', ''),
  (1, 2, 'Modern Database Development Tools', '02-01-2018', ''),
  (3, 3, 'Test Driven Database Development (TDDD)', '03-01-2018', ''),
  (3, 1, 'Database Unit Testing Fundamentals', '10-01-2018', ''),
  (3, 3, 'Unit Testing with tSQLt', '10-01-2018', '')
GO
 

Buat tampilan untuk melihat daftar semua penulis, artikel, dan kategori artikel:

-- (7) Create a view to see a list of authors, articles, and categories
CREATE VIEW dbo.vwAuthors 
AS SELECT a.Name AS AuthorName,a1.Title AS ArticleTitle,c.Name AS CategoryName  FROM Author a INNER JOIN Article a1 ON a.AuthorId = a1.AuthorId INNER JOIN Category c ON a1.CategoryId = c.CategoryId
GO
 

Jalankan tampilan tabel yang dibuat untuk melihat hasilnya:

Setelah memproses penyiapan database dan mengisi tabel, langkah selanjutnya adalah meniru skenario saat kita menerima persyaratan baru.

Persyaratan Bisnis:Jumlah Total Artikel per Penulis Laporan

Pertimbangkan persyaratan pelaporan bisnis baru. Itu harus menyatakan laporan basis data untuk melihat jumlah total artikel per penulis.

Hal pertama adalah menetapkan objek database yang dapat memenuhi kebutuhan bisnis. Dalam kasus kami, ini adalah ArticlesPerAuthorReport objek basis data.

Untuk memenuhi kebutuhan tersebut, perlu dibuat database unit test yang mencari objek potensial yang sesuai. Seperti yang kita ketahui, tes ini akan gagal terlebih dahulu karena akan mencari objek yang tidak ada saat ini tetapi akan segera ada.

Rencana Implementasi TDDD

Menurut standar pengujian unit basis data yang digerakkan oleh pengujian, hal-hal berikut harus ada untuk memenuhi persyaratan pelaporan:

  1. Mengembangkan objek database tunggal yang akan memenuhi persyaratan pelaporan.
  2. Buat pengujian unit untuk memeriksa keberadaan objek.
  3. Buat rintisan objek (placeholder) untuk lulus tes pertama.
  4. Buat pengujian unit kedua untuk memeriksa apakah objek mengeluarkan data yang benar ke dalam tabel dengan masukan yang benar.
  5. Ubah definisi objek agar tes kedua lulus.

Buat Pengujian Unit Basis Data untuk Memeriksa Keberadaan Objek yang Diinginkan

Kami akan menetapkan objek database yang dapat memenuhi kebutuhan bisnis. Dalam kasus kami, ini adalah ArticlesPerAuthorReport objek basis data. Langkah selanjutnya adalah membuat pengujian unit basis data.

Untuk membuat pengujian unit database pertama, klik kanan SQLDevBlogReport database> Uji Unit > Tambahkan Tes Baru

Tulis kode berikut untuk membuat unit test yang memeriksa ada tidaknya objek yang diinginkan:

CREATE PROCEDURE ArticlesPerAuthorReport.[test to check ArticlesPerAuthorReport exists]
AS
BEGIN
  --Assemble
 
  --Act
  
  --Assert
   EXEC tSQLt.AssertObjectExists @ObjectName = N'ArticlesPerAuthorReport'
END;
GO
 

Tes unit harus gagal karena memeriksa objek yang dibuat sebelumnya. Objek itu sendiri dibuat untuk mematuhi TDDD:

Buat Object Stub dan Jalankan Unitnya

Buat rintisan objek dengan beberapa keluaran yang diharapkan dengan hard-coded, karena kita hanya ingin membuat objek database dengan hasil yang diharapkan. Buat ArticlesPerAuthorReport objek sebagai rintisan tampilan (placeholder) pada awalnya:

-- (8) Create ArticlesPerAuthorReport view stub
  CREATE VIEW ArticlesPerAuthorReport
    AS
    SELECT 'Adil' AS Author, 10 AS [Total Articles]
    UNION ALL
    SELECT 'Sam' AS Author, 5 AS [Total Articles]
 

Menjalankan unit test harus berhasil:

Membuat rintisan berfungsi sebagai kick-starter untuk TDDD. Kami membuat objek untuk lulus tes dan tidak peduli tentang fungsi objek yang sebenarnya.

Buat dan Jalankan Unit Test untuk memeriksa apakah Objek Menghasilkan Data yang Benar

Saatnya untuk memeriksa apakah objek yang diinginkan berfungsi dengan baik. Buat pengujian unit lain untuk memeriksa keluaran data menurut objek yang diinginkan (ArticlesPerAuthorReport ). Mari tambahkan unit test baru ke database:

Tambahkan kode unit test berikut:

CREATE PROCEDURE ArticlesPerAuthorReport.[test to check ArticlesPerAuthorReport outputs correct]
AS
BEGIN
  --Assemble
  --  Create mocked up tables (blank copies of original tables without constraints and data)
  EXEC tSQLt.FakeTable @TableName = N'Author'
                      ,@SchemaName = N'dbo'

  EXEC tSQLt.FakeTable @TableName = N'Article'
                      ,@SchemaName = N'dbo'                      

  EXEC tSQLt.FakeTable @TableName = N'Category'
                      ,@SchemaName = N'dbo'                      

  -- Add rows to the mocked up tables
  INSERT INTO Author (AuthorId,Name, RegistrationDate, Notes)
  VALUES (1,'Zak', DATEFROMPARTS(2017,01,01), 'Database Author'),
    (2,'Akeel',DATEFROMPARTS(2018,01,01),'Business Intelligence Author')
  
  INSERT INTO Category (CategoryID,Name, Notes)
  VALUES (1,'Database Development', '-'),
  (2,'Business Intelligene','-');

  INSERT INTO Article (ArticleId,CategoryId, AuthorId, Title, Published, Notes)
  VALUES (1,1, 1, 'Advanced Database Development', DATEFROMPARTS(2017,02,01),'10K Views'),
  (1,1, 1, 'Database Development with Cloud Technologies', DATEFROMPARTS(2017,02,01),'5K Views'),
  (1,1, 1, 'Developing Databases with Modern Tools', DATEFROMPARTS(2017,03,01),'20K Views'),
  (1,2, 2, 'Business Intelligence Fundamentals', DATEFROMPARTS(2017,02,01),'10K Views'),
  (1,2, 2, 'Tabular Models', DATEFROMPARTS(2017,02,01),'50K Views')

  -- Create an expected table
  CREATE TABLE ArticlesPerAuthorReport.Expected
  (Author VARCHAR(40),[Total Articles] int)  

  -- Add expected results into an expected table
  INSERT INTO ArticlesPerAuthorReport.Expected (Author, [Total Articles])
  VALUES ('Zak', 3), ('Akeel',2);


  --Act
  --  Run ArticlesPerAuthorReport object (view) and put results into an actual table
  SELECT * INTO ArticlesPerAuthorReport.Actual FROM ArticlesPerAuthorReport apar
  

  --Assert
  --  Compare the expected and actual tables
  EXEC TSQLT.AssertEqualsTable @Expected = N'ArticlesPerAuthorReport.Expected'
                              ,@Actual = N'ArticlesPerAuthorReport.Actual'
                              

END;
GO
 

Jalankan unit test yang harus gagal juga untuk mematuhi TDDD:

Tambahkan Fungsionalitas yang Diperlukan ke objek ArticlesPerAuthorReport

Pengujian unit yang memeriksa fungsionalitas objek memerlukan struktur yang dimodifikasi agar pengujian dapat lulus.

Ubah ArticlesPerAuthorReport tampilan untuk membiarkan tes unit kedua lulus seperti yang pertama:

ALTER VIEW ArticlesPerAuthorReport
  AS
SELECT a.Name AS [Author],COUNT(a1.ArticleId) AS [Total Articles] FROM Author a 
    INNER JOIN Article a1 ON a.AuthorId = a1.AuthorId
    GROUP BY a.Name
 

Objek database telah berhasil dimodifikasi untuk menghasilkan data yang diinginkan. Jalankan semua pengujian unit:

ArticlesPerAuthorReport objek sudah siap.

Tugas kita selanjutnya adalah memberikan panduan dalam membuat basis laporan pada objek database yang dikembangkan dan diuji dengan menggunakan pengembangan yang digerakkan oleh pengujian (TDDD).

Menerapkan Persyaratan Pelaporan (ArticlesPerAuthorReport)

Pertama, kita akan mengatur ulang SQLDevBlogReportTDD dan menambahkan lebih banyak data ke dalamnya. Atau, Anda dapat membuat database kosong untuk pertama kalinya.

Untuk menambahkan cukup data ke database sampel kami, ambil data dari vwAuthors view untuk melihat semua record:

Menjalankan pengujian unit

Jalankan pengujian unit database yang kita buat sebelumnya:

Selamat, kedua pengujian telah lulus yang berarti objek database yang diinginkan mampu memenuhi persyaratan pelaporan untuk melihat artikel per penulis.

Membuat Laporan Basis Data Berdasarkan ArticlesPerAuthorsReport Object

Anda dapat membuat laporan database dengan berbagai cara (seperti menggunakan Pembuat Laporan, membuat Proyek Server Laporan di Alat Data Visual Studio, atau menggunakan dbForge Studio untuk SQL Server).

Di bagian ini, kami menggunakan dbForge Studio untuk SQL Server untuk pembuatan laporan. Untuk melanjutkan, klik Baru dari File Menu> Laporan Data :

Klik Laporan Standar :

Pilih Tabel Sederhana\Tampilan sebagai Jenis Data :

Tambahkan objek dasar (ArticlesPerAuthorReport ), yang merupakan tampilan dalam kasus kami:

Tambahkan bidang wajib:

Kami tidak memerlukan pengelompokan apa pun pada saat ini, jadi lanjutkan dengan mengeklik Berikutnya :

Pilih Tata Letak dan Orientasi dari laporan data:

Terakhir, tambahkan judul Artikel per Laporan Penulis dan klik Selesai :

Selanjutnya, sesuaikan format laporan sesuai kebutuhan:

Klik Pratinjau untuk melihat laporan basis data:

Simpan laporan sebagai ArticlesPerAuthorReport . Laporan database telah dibuat karena kebutuhan bisnis.

Penggunaan Prosedur Pengaturan

Saat Anda menulis pengujian unit database menggunakan tSQLt, Anda akan melihat bahwa beberapa kode pengujian sering diulang. Dengan demikian, Anda dapat mendefinisikannya dalam prosedur penyiapan dan menggunakannya kembali setelahnya dalam pengujian unit lain dari kelas pengujian tertentu tersebut. Setiap kelas pengujian hanya dapat memiliki satu prosedur penyiapan yang berjalan secara otomatis sebelum pengujian unit dari proses kelas tersebut.

Kami dapat menempatkan hampir semua kode pengujian yang ditulis di bawah Assemble (bagian) di bawah prosedur penyiapan untuk menghindari duplikasi kode.

Misalnya, kita perlu membuat tabel tiruan bersama dengan tabel yang diharapkan. Kemudian kita akan menambahkan data ke tabel tiruan, dan kemudian ke tabel yang diharapkan. Kita dapat mendefinisikannya dengan mudah di bawah prosedur penyiapan dan menggunakannya kembali lebih lanjut.

Membuat Prosedur Pengaturan untuk menghindari duplikasi kode pengujian

Buat prosedur tersimpan di SQLDevBlogTDD sebagai berikut:

-- (12) Use of Setup Procedure to avoid repeating common test code
CREATE PROCEDURE ArticlesPerAuthorReport.Setup 
AS 
BEGIN
  --Assemble
  --  Create mocked up tables (blank copies of original tables without constraints and data)
  EXEC tSQLt.FakeTable @TableName = N'Author'
                      ,@SchemaName = N'dbo'

  EXEC tSQLt.FakeTable @TableName = N'Article'
                      ,@SchemaName = N'dbo'                      

  EXEC tSQLt.FakeTable @TableName = N'Category'
                      ,@SchemaName = N'dbo'                      

  -- Add rows to the mocked up tables
  INSERT INTO Author (AuthorId,Name, RegistrationDate, Notes)
  VALUES (1,'Zak', DATEFROMPARTS(2017,01,01), 'Database Author'),
    (2,'Akeel',DATEFROMPARTS(2018,01,01),'Business Intelligence Author')
  
  INSERT INTO Category (CategoryID,Name, Notes)
  VALUES (1,'Database Development', '-'),
  (2,'Business Intelligene','-');

  INSERT INTO Article (ArticleId,CategoryId, AuthorId, Title, Published, Notes)
  VALUES (1,1, 1, 'Advanced Database Development', DATEFROMPARTS(2017,02,01),'10K Views'),
  (1,1, 1, 'Database Development with Cloud Technologies', DATEFROMPARTS(2017,02,01),'5K Views'),
  (1,1, 1, 'Developing Databases with Modern Tools', DATEFROMPARTS(2017,03,01),'20K Views'),
  (1,2, 2, 'Business Intelligence Fundamentals', DATEFROMPARTS(2017,02,01),'10K Views'),
  (1,2, 2, 'Tabular Models', DATEFROMPARTS(2017,02,01),'50K Views')

  -- Create an expected table
  CREATE TABLE ArticlesPerAuthorReport.Expected
  (Author VARCHAR(40),[Total Articles] int)  

  -- Add expected results into an expected table
  INSERT INTO ArticlesPerAuthorReport.Expected (Author, [Total Articles])
  VALUES ('Zak', 3), ('Akeel',2)
END;
GO
 

Sekarang, hapus kode pengujian yang telah kita tulis dalam prosedur penyiapan dari pengujian unit sebelumnya untuk memeriksa ArticlesPerAuthorReport output sebagai berikut:

-- (11) Create unit test check ArticlesPerAuthorReport outputs correct
ALTER PROCEDURE ArticlesPerAuthorReport.[test to check ArticlesPerAuthorReport outputs correct]
AS
BEGIN
  --Assemble (Test Code written in Setup Procedure)
  -- Create mocked up tables (blank copies of original tables without constraints and data)
  -- Add rows to the mocked up tables
  -- Create an expected table
  -- Add expected results into an expected table
  
  --Act
  --  Run ArticlesPerAuthorReport object (view) and put results into an actual table
  SELECT * INTO ArticlesPerAuthorReport.Actual FROM ArticlesPerAuthorReport apar
  

  --Assert
  --  Compare the expected and actual tables
  EXEC TSQLT.AssertEqualsTable @Expected = N'ArticlesPerAuthorReport.Expected'
                              ,@Actual = N'ArticlesPerAuthorReport.Actual'
                              
END;
GO
 

Running All Unit Tests to Check Setup Procedure Working

Run the unit tests and see the results:

The unit tests have run successfully despite the fact we are using a setup procedure to run some parts of the test code before these unit tests are running.

Use of Stored Procedures

Next, we’ll focus on creating stored procedures through test-driven database development (TDDD) to meet specific requirements that cannot be fulfilled by using a database view.

Let’s assume that business users want to know the Total number of articles per author for a specified year . The database view can’t meet it because it is not defined at the time of writing the script (exactly the year is going to be desired by the business users).

Thus, it requires a database object with parameter(s) capability and it is exactly the stored procedure.

Let us consider a new business requirement to create the report that shows the total number of articles per author for a specified year . We’ll use the sample database called SQLDevBlogReportTDD that we created earlier.

Run the ArticlesPerAuthorReport view to see the results:

Select the Database Object (AuthorsPerArticleByYearReport)

Name the potential database object as AuthorsPerArticleForYearReport .

As we mentioned above, the database view can meet the reporting requirement despite the absence of the specified year . But this variable means that we need the stored procedure which will pass year as an argument to run the report and show the desired results.

Write and Run the Object Exists Unit Test

As we already know, we need to start with writing the basic unit test to check the existence or absence of the desired object.

To create the first database unit test, right-click the SQLDevBlogReport database> Unit Test > Add New Test

Write the following test code:

CREATE PROCEDURE ArticlesPerAuthorByYearReport.[test to check ArticlesPerAuthorByYearReport exists]

AS

BEGIN

--Assemble

--Act

--Assert

EXEC tSQLt.AssertObjectExists @ObjectName = N'ArticlesPerAuthorByYearReport'

,@Message = N''


END;

GO
 

Right-click on the database> click View Test List under Unit Test to see the Test List Manager :

Check the ArticlesPerAuthorByYearReport test class and click the run test icon:

This complies with TDDD – the unit test checking if object existence is written before the object is created. So, we expect the test to fail first.

Create Object Stub (dummy object)

We are going to create an object stub that mocks the object’s functionality. At this stage, we only need that object, the desired functionality is out of the question.

Create a stored procedure type object as the stub and call it ArticlesPerAuthorByYearReport by using the following code:

-- Create report object (stored procedure) stub

CREATE PROCEDURE dbo.ArticlesPerAuthorByYearReport

@Year INT

AS

SELECT 'Adil' AS Author, 10 AS [Total Articles], 0000 AS [Year]

UNION ALL

SELECT 'Sam' AS Author, 5 AS [Total Articles], 0000 AS [Year]

GO
 

After we created the object stub, the basic unit test that checks for the existence of the object will be successful:

Write and Run the Object Functionality Unit Test

To comply with TDDD, we need to write a unit test to check whether the desired object ArticlesPerAuthorByYearReport functions properly. Since the object was created as a stub (placeholder), this unit test is also going to fail first. The object has to function properly yet despite the fact it was created and passed the basic check of its existence.

Create a second unit test to check if the object outputs correct data by creating a setup procedure (which helps us to write shared test code within the same test class) that is followed by the unit test:

CREATE PROCEDURE ArticlesPerAuthorByYearReport. Setup

AS

BEGIN

--Assemble

-- Create mocked up tables (blank copies of original tables without constraints and data)

EXEC tSQLt.FakeTable @TableName = N'Author'

,@SchemaName = N'dbo'




EXEC tSQLt.FakeTable @TableName = N'Article'

,@SchemaName = N'dbo'




EXEC tSQLt.FakeTable @TableName = N'Category'

,@SchemaName = N'dbo'




-- Add rows to the mocked up tables

INSERT INTO Author (AuthorId,Name, RegistrationDate, Notes)

VALUES (1,'Zak', DATEFROMPARTS(2017,01,01), 'Database Author'),

(2,'Akeel',DATEFROMPARTS(2018,01,01),'Business Intelligence Author')

INSERT INTO Category (CategoryID,Name, Notes)

VALUES (1,'Database Development', '-'),

(2,'Business Intelligene','-');




INSERT INTO Article (ArticleId,CategoryId, AuthorId, Title, Published, Notes)

VALUES (1,1, 1, 'Advanced Database Development', DATEFROMPARTS(2017,02,01),'10K Views'),

(1,1, 1, 'Database Development with Cloud Technologies', DATEFROMPARTS(2017,02,01),'5K Views'),

(1,1, 1, 'Developing Databases with Modern Tools', DATEFROMPARTS(2017,03,01),'20K Views'),

(1,2, 2, 'Business Intelligence Fundamentals', DATEFROMPARTS(2016,02,01),'10K Views'),

(1,2, 2, 'Tabular Models', DATEFROMPARTS(2016,02,01),'50K Views')




-- Create an expected table

CREATE TABLE ArticlesPerAuthorByYearReport.Expected

(Author VARCHAR(40),[Total Articles] INT,[Year] INT)




-- Create an actual table

CREATE TABLE ArticlesPerAuthorByYearReport.Actual

(Author VARCHAR(40),[Total Articles] INT,[Year] INT)




-- Add expected results into an expected table for the year 2017

INSERT INTO ArticlesPerAuthorByYearReport.Expected (Author, [Total Articles],[Year])

VALUES ('Zak', 3,2017)




END;

GO
 

Write the unit test to check if the object functions properly:

-- Create unit test to check ArticlesPerAuthorByYearReport outputs correct data

CREATE PROCEDURE ArticlesPerAuthorByYearReport.[test to check ArticlesPerAuthorByYearReport outputs correct data]

AS

BEGIN

--Assemble (Test Code written in Setup Procedure)

-- Create mocked up tables (blank copies of original tables without constraints and data)

-- Add rows to the mocked up tables

-- Create an expected table

-- Create an actual table

-- Add expected results into an expected table

--Act

-- Call desired object (stored procedure) and put results into an actual table

INSERT INTO ArticlesPerAuthorByYearReport.Actual

EXEC dbo.ArticlesPerAuthorByYearReport @Year=2017




--Assert

-- Compare the expected and actual tables

EXEC TSQLT.AssertEqualsTable @Expected = N'ArticlesPerAuthorByYearReport.Expected'

,@Actual = N'ArticlesPerAuthorByYearReport.Actual'

END;

GO
 

Run the unit test. As demonstrated earlier, it will fail first since we have not added the desired functionality to the object yet:

Add Object Functionality and Rerun the Unit Test

Add the object functionality by modifying the stored procedure as follows:

-- Create report object (stored procedure) to show articles per author for a specified year

CREATE PROCEDURE dbo.ArticlesPerAuthorByYearReport

@Year INT

AS




SELECT

a.Name AS [Author],COUNT(a1.ArticleId) AS [Total Articles],YEAR(a.RegistrationDate) AS [Year]

FROM Author a

INNER JOIN Article a1

ON a.AuthorId = a1.AuthorId

WHERE YEAR(a.RegistrationDate) = @Year

GROUP BY a.Name,YEAR(a.RegistrationDate)

GO
 

Note :If you are using a declarative database development tool like dbForge Studio for SQL Server, you’ll use the Create Procedure statement to modify the object. For tools like SSMS (SQL Server Management Studio), you must use ALTER Procedure .

Rerunning the database unit test for checking the proper object functioning gives us the following results:

You have successfully unit tested the reporting procedure that is responsible for meeting the business requirement.

Kesimpulan

Test-driven database development (TDDD) is a specific approach. To meet the business requirement(s), potential database object(s) must pass the unit test(s) and satisfy the following conditions under normal circumstances:

  • The database object must exist
  • The database object must function properly to meet the business requirement

First, the unit tests have to fail because they are created before the creation of the object/defining the object functionality. After adding the necessary objects and ensuring their functionality, the unit tests succeed.

This article examined the basics of test-driven database development and illustrated it with practical examples. We hope that the article was helpful to you. Feel free to share your opinions and maybe some lifehacks in the Comments section, and stay tuned for the next materials!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cara Menyalin Data Dari Satu Tabel ke Tabel Lainnya di SQL

  2. Pengantar Pemrosesan Asinkron dengan Pialang Layanan

  3. Pemeriksaan Kesehatan pada Exadata Menggunakan Exachk Utility

  4. Menggunakan Data Protected dengan Custom Key Store dari Linux

  5. Migrasi Proyek Django Anda ke Heroku