Database
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Database

Bước tới Bắt đầu Phát triển Cơ sở dữ liệu Theo hướng Thử nghiệm (TDDD)

Theo quy định, chúng tôi bắt đầu phát triển các giải pháp cơ sở dữ liệu bằng cách tạo các đối tượng cơ sở dữ liệu, chẳng hạn như bảng, dạng xem, thủ tục được lưu trữ, v.v., dựa trên các yêu cầu nghiệp vụ. Cách tiếp cận này còn được gọi là Phát triển cơ sở dữ liệu thông thường . Trong bài viết này, chúng ta sẽ khám phá cách tiếp cận này và minh họa nó bằng các ví dụ.

Phát triển cơ sở dữ liệu thông thường

Phong cách phát triển bao gồm các bước sau:

  1. Nhận các yêu cầu
  2. Tạo các đối tượng cơ sở dữ liệu dựa trên các yêu cầu
  3. Chạy các bài kiểm tra đơn vị cho các đối tượng cơ sở dữ liệu để xem liệu chúng có đáp ứng các yêu cầu không
  4. Nhận các yêu cầu mới
  5. Sửa đổi các đối tượng cơ sở dữ liệu hiện có hoặc thêm các đối tượng mới để đáp ứng các yêu cầu mới
  6. Tạo và chạy các bài kiểm tra đơn vị để kiểm tra xem các yêu cầu mới có hoạt động phù hợp và không xung đột với các yêu cầu trước đó hay không

Để khám phá và minh họa các quy trình, chúng ta hãy bắt đầu với việc thiết lập cơ sở dữ liệu mẫu SQLDevBlog :

 
-- Create sample database (SQLDevBlog)
  CREATE DATABASE SQLDevBlog

Sử dụng mã sau để tạo bảng trong cơ sở dữ liệu mẫu đó:

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

Xem lại sơ đồ cơ sở dữ liệu với các bảng mới tạo của chúng tôi:

Lưu ý :Tôi đang sử dụng ở đây dbForge Studio cho SQL Server để thực hiện tất cả các tác vụ. Giao diện đầu ra của nó có thể khác với SSMS (SQL Server Management Studio), nhưng kết quả thì giống nhau.

Tiếp theo, chúng tôi sẽ điền SQLDevBlog của chúng tôi cơ sở dữ liệu mẫu để tạo ra một kịch bản thực tế hơn:

-- (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

Kết quả là chúng ta có các bảng được điền sau đây:

Bây giờ chúng ta đã hoàn thành việc thiết lập cơ sở dữ liệu và tập hợp bảng, chúng ta phải đối mặt với bước tiếp theo. Chúng tôi phải bắt chước kịch bản với một yêu cầu mới.

Yêu cầu thêm một danh mục mới

Yêu cầu mới nêu rõ rằng quản trị viên có thể thêm một danh mục mới vào danh sách các danh mục có sẵn . Để đáp ứng yêu cầu này, nhóm phát triển của bạn phải đưa ra một quy trình được lưu trữ để thêm một yêu cầu mới một cách dễ dàng. Hoặc, chúng tôi phải tạo AddCategory Đối tượng Cơ sở dữ liệu.

Để tạo quy trình được lưu trữ, hãy chạy tập lệnh sau:

-- (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

Kết quả như sau:

Tạo Kiểm tra Đơn vị Cơ sở dữ liệu để Kiểm tra xem Quy trình có hoạt động đúng không

Bước tiếp theo là tạo kiểm tra đơn vị cơ sở dữ liệu để kiểm tra xem thủ tục được lưu trữ có đáp ứng đặc điểm kỹ thuật hay không.

Mẹo này hoạt động cho dbForge Studio dành cho SQL Server (hoặc chỉ Kiểm tra đơn vị dbForge ) SSMS (SQL Server Management Studio) . Lưu ý:Khi sử dụng SSMS (SQL Server Management Studio), hãy đảm bảo cài đặt tSQLt Khung để viết các bài kiểm tra đơn vị.

Để tạo kiểm tra đơn vị cơ sở dữ liệu đầu tiên, hãy nhấp chuột phải vào SQLDevBlog cơ sở dữ liệu> Unit Test > Thêm thử nghiệm mới

Thêm thử nghiệm mới cửa sổ mở ra. Điền vào tất cả các thông tin được yêu cầu và nhấp vào Thêm kiểm tra .

Tạo bài kiểm tra đơn vị như sau và lưu nó:

--  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

Nhấp vào Cơ sở dữ liệu trình đơn> Kiểm tra đơn vị > Xem danh sách kiểm tra và chạy thử nghiệm đơn vị như được hiển thị bên dưới:

Chúng ta có thể thấy rằng bài kiểm tra đơn vị đã thành công. Do đó, một danh mục mới có thể được thêm vào cơ sở dữ liệu (bảng). Yêu cầu đã được đáp ứng.

Bây giờ, chúng ta sẽ khám phá sự phát triển cơ sở dữ liệu theo hướng thử nghiệm và mô tả cách quá trình viết các bài kiểm tra đơn vị có thể đáp ứng các yêu cầu.

Phát triển cơ sở dữ liệu theo hướng thử nghiệm (TDDD)

Phát triển cơ sở dữ liệu theo hướng kiểm tra (TDDD) bắt đầu bằng việc viết bài kiểm tra đơn vị sẽ không thành công trước. Sau đó, chúng tôi sẽ sửa đổi nó để vượt qua và sau đó tinh chỉnh nó.

Bài kiểm tra đơn vị được viết để đáp ứng các yêu cầu và bài kiểm tra đơn vị yêu cầu các đối tượng cơ sở dữ liệu phải được tạo và chạy đúng cách.

Để hiểu sự khác biệt giữa phát triển cơ sở dữ liệu truyền thống và phát triển cơ sở dữ liệu theo hướng thử nghiệm, chúng ta hãy tạo SQLDevBlogTDD cơ sở dữ liệu. Nó giống với SQLDevBlog .

-- Create sample database (SQLDevBlogTDD)
  CREATE DATABASE SQLDevBlogTDD

Sau đó, điền vào cơ sở dữ liệu mẫu bằng các bảng:

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

Chúng tôi phải điền vào cơ sở dữ liệu mẫu của mình để tạo ra một kịch bản thực tế hơn như sau:

-- 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

Yêu cầu thêm danh mục mới (TDDD)

Bây giờ, chúng tôi có cùng một yêu cầu:quản trị viên có thể thêm một danh mục mới vào danh sách các danh mục có sẵn. Để đáp ứng yêu cầu này, trước tiên chúng ta cần viết một bài kiểm tra đơn vị cơ sở dữ liệu để tìm kiếm một đối tượng tiềm năng.

Đó là cách TDDD hoạt động:thử nghiệm đơn vị đầu tiên không thành công vì chúng tôi giả định rằng chúng tôi đang tìm kiếm đối tượng hiện không tồn tại, nhưng nó sẽ sớm có.

Tạo và chạy Kiểm tra đơn vị cơ sở dữ liệu để kiểm tra sự tồn tại của đối tượng mong muốn

Mặc dù chúng tôi biết rằng nó không tồn tại bây giờ, nhưng chúng tôi coi đây là điểm khởi đầu.

Trong dbForge Studio dành cho SQL Server, kiểm tra đơn vị cơ sở dữ liệu hỗ trợ TDDD theo mặc định được tạo ra trước tiên không thành công. Sau đó, chúng tôi sẽ thay đổi nó một chút. Nếu bạn đang sử dụng tSQLt trực tiếp khung kiểm tra đơn vị cơ sở dữ liệu, viết kiểm thử đơn vị sau:

--  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

Sau khi bạn chạy kiểm tra đơn vị cơ sở dữ liệu, bạn có thể thấy rằng kiểm tra không thành công:

Tạo đối tượng cơ sở dữ liệu và chạy lại đơn vị kiểm tra

Bước tiếp theo là tạo đối tượng cơ sở dữ liệu cần thiết. Trong trường hợp của chúng tôi, đó là một thủ tục được lưu trữ.

-- (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

Chạy lại bài kiểm tra đơn vị - lần này nó thành công:

Nhưng nó không đủ để vượt qua kiểm tra đơn vị nếu thủ tục được lưu trữ tồn tại. Chúng tôi cũng cần kiểm tra xem thủ tục được lưu trữ có thêm một danh mục mới hay không.

Tạo Kiểm tra Đơn vị Cơ sở dữ liệu để Kiểm tra xem Quy trình hoạt động có đúng không

Hãy tạo thử nghiệm đơn vị cơ sở dữ liệu mới:

--  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

Như bạn có thể thấy, thử nghiệm đơn vị không thành công lần đầu tiên và thành công lần thứ hai:

Thêm chức năng vào Quy trình và Chạy lại Đơn vị Kiểm tra

Sửa đổi quy trình đã lưu trữ bằng cách thêm chức năng cần thiết để quá trình kiểm tra có thể thành công như hình dưới đây:

-- (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

Chạy lại các bài kiểm tra đơn vị để kiểm tra xem tất cả chúng đều thành công bao gồm cả quy trình được lưu trữ được sửa đổi gần đây:

Bằng cách này, chúng tôi đã triển khai thành công phát triển cơ sở dữ liệu hướng thử nghiệm. Bây giờ chúng ta chỉ có thể tập trung vào các yêu cầu. Các bài kiểm tra đơn vị đóng gói các yêu cầu do đó yêu cầu các đối tượng cơ sở dữ liệu phải được tạo và chạy đúng cách để đáp ứng đặc điểm kỹ thuật.

Hãy xem TDDD hiệu quả như thế nào khi đáp ứng yêu cầu báo cáo kinh doanh.

Đáp ứng Yêu cầu Báo cáo Kinh doanh thông qua TDDD

Chúng tôi giả định rằng cơ sở dữ liệu đã có các đối tượng cần thiết (chẳng hạn như bảng) trước khi nhận được yêu cầu báo cáo kinh doanh mới.

Hãy tạo cơ sở dữ liệu mẫu có tên SQLDevBlogReportTDD :

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

Sau đó, tạo và điền các bảng cho cơ sở dữ liệu mẫu bằng mã sau:

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

Tạo chế độ xem để xem danh sách tất cả các tác giả, bài báo và danh mục của bài báo:

-- (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

Chạy chế độ xem bảng đã tạo để xem kết quả:

Sau khi xử lý thiết lập cơ sở dữ liệu và điền các bảng, bước tiếp theo là bắt chước tình huống mà chúng tôi nhận được một yêu cầu mới.

Yêu cầu kinh doanh:Tổng số bài báo trên mỗi báo cáo của tác giả

Xem xét một yêu cầu báo cáo kinh doanh mới. Nó phải nêu một báo cáo cơ sở dữ liệu để xem tổng số bài báo của mỗi tác giả.

Điều đầu tiên là gán một đối tượng cơ sở dữ liệu có thể đáp ứng các yêu cầu kinh doanh. Trong trường hợp của chúng tôi, đó là ArticlesPerAuthorReport đối tượng cơ sở dữ liệu.

Để đáp ứng yêu cầu này, cần tạo một bài kiểm tra đơn vị cơ sở dữ liệu để tìm kiếm một đối tượng thích hợp tiềm năng. Như chúng ta đã biết, thử nghiệm này sẽ không thành công trước tiên vì nó sẽ tìm kiếm đối tượng không tồn tại tại thời điểm này nhưng sẽ sớm xuất hiện.

Kế hoạch thực hiện TDDD

Theo tiêu chuẩn của thử nghiệm đơn vị cơ sở dữ liệu hướng thử nghiệm, những điều sau đây phải có để đáp ứng yêu cầu báo cáo:

  1. Phát triển một đối tượng cơ sở dữ liệu duy nhất sẽ đáp ứng yêu cầu báo cáo.
  2. Tạo một bài kiểm tra đơn vị để kiểm tra sự tồn tại của đối tượng.
  3. Tạo một bản gốc đối tượng (trình giữ chỗ) để vượt qua thử nghiệm đầu tiên.
  4. Tạo một bài kiểm tra đơn vị thứ hai để kiểm tra xem đối tượng có xuất dữ liệu chính xác vào bảng với đầu vào chính xác hay không.
  5. Sửa đổi định nghĩa đối tượng để cho phép thử nghiệm thứ hai vượt qua.

Tạo Kiểm tra Đơn vị Cơ sở dữ liệu để Kiểm tra Sự tồn tại của Đối tượng Mong muốn

Chúng tôi sẽ chỉ định một đối tượng cơ sở dữ liệu có thể đáp ứng yêu cầu kinh doanh. Trong trường hợp của chúng tôi, đó là ArticlesPerAuthorReport đối tượng cơ sở dữ liệu. Bước tiếp theo là tạo kiểm tra đơn vị cơ sở dữ liệu.

Để tạo kiểm tra đơn vị cơ sở dữ liệu đầu tiên, hãy nhấp chuột phải vào SQLDevBlogReport cơ sở dữ liệu> Unit Test > Thêm thử nghiệm mới

Viết đoạn mã sau để tạo bài kiểm tra đơn vị để kiểm tra sự tồn tại hay vắng mặt của đối tượng mong muốn:

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

Kiểm thử đơn vị phải không thành công vì nó kiểm tra đối tượng được tạo trước đó. Bản thân đối tượng được tạo để tuân thủ TDDD:

Tạo Object Stub và chạy Unit

Tạo một sơ khai đối tượng với một số đầu ra dự kiến ​​được mã hóa cứng, vì chúng ta chỉ muốn tạo một đối tượng cơ sở dữ liệu với kết quả mong đợi. Tạo ArticlesPerAuthorReport đối tượng dưới dạng sơ khai chế độ xem (trình giữ chỗ) lúc đầu:

-- (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]

Chạy thử nghiệm đơn vị sẽ thành công:

Tạo sơ khai đóng vai trò như một bước khởi động cho TDDD. Chúng tôi tạo đối tượng để vượt qua bài kiểm tra và không bận tâm về hoạt động thực tế của đối tượng.

Tạo và chạy Unit Test để kiểm tra xem liệu đầu ra của đối tượng có đúng dữ liệu hay không

Đã đến lúc kiểm tra xem đối tượng mong muốn có hoạt động bình thường hay không. Tạo một bài kiểm tra đơn vị khác để kiểm tra đầu ra dữ liệu của đối tượng mong muốn ( ArticlesPerAuthorReport ). Hãy thêm một bài kiểm tra đơn vị mới vào cơ sở dữ liệu:

Thêm mã kiểm tra đơn vị sau:

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

Chạy thử nghiệm đơn vị không đạt yêu cầu tuân thủ TDDD:

Thêm chức năng cần thiết vào đối tượng ArticlesPerAuthorReport

Bài kiểm tra đơn vị để kiểm tra chức năng của đối tượng yêu cầu cấu trúc được sửa đổi để bài kiểm tra có thể vượt qua.

Sửa đổi ArticlesPerAuthorReport để cho phép bài kiểm tra đơn vị thứ hai vượt qua giống như bài kiểm tra đầu tiên:

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

Đối tượng cơ sở dữ liệu đã được sửa đổi thành công để xuất ra dữ liệu mong muốn. Chạy tất cả các bài kiểm tra đơn vị:

ArticlePerAuthorReport đối tượng đã sẵn sàng.

Nhiệm vụ tiếp theo của chúng tôi là cung cấp hướng dẫn cách tạo cơ sở báo cáo trên đối tượng cơ sở dữ liệu được phát triển và thử nghiệm bằng cách sử dụng phát triển theo hướng thử nghiệm (TDDD).

Thực hiện yêu cầu báo cáo (ArticlesPerAuthorReport)

Đầu tiên, chúng tôi sẽ đặt lại SQLDevBlogReportTDD và thêm nhiều dữ liệu vào nó. Hoặc, bạn có thể tạo cơ sở dữ liệu trống lần đầu tiên.

Để thêm đủ dữ liệu vào cơ sở dữ liệu mẫu của chúng tôi, hãy truy xuất dữ liệu từ vwAuthors xem để xem tất cả các bản ghi:

Chạy các bài kiểm tra đơn vị

Chạy các bài kiểm tra đơn vị cơ sở dữ liệu mà chúng tôi đã tạo trước đó:

Xin chúc mừng, cả hai bài kiểm tra đều đã vượt qua, có nghĩa là đối tượng cơ sở dữ liệu mong muốn có khả năng đáp ứng yêu cầu báo cáo để xem các bài báo cho mỗi tác giả.

Tạo báo cáo cơ sở dữ liệu dựa trên đối tượng ArticlesPerAuthorsReport

Bạn có thể tạo báo cáo cơ sở dữ liệu theo nhiều cách (chẳng hạn như sử dụng Trình tạo báo cáo, tạo Dự án máy chủ báo cáo trong Công cụ dữ liệu Visual Studio hoặc sử dụng dbForge Studio cho SQL Server).

Trong phần này, chúng tôi đang sử dụng dbForge Studio cho SQL Server để tạo báo cáo. Để tiếp tục, hãy nhấp vào Mới từ Tệp Trình đơn> Báo cáo dữ liệu :

Nhấp vào Báo cáo chuẩn :

Chọn Bảng đơn giản \ Xem dưới dạng Loại dữ liệu :

Thêm đối tượng cơ sở ( ArticlesPerAuthorReport ), đó là một chế độ xem trong trường hợp của chúng tôi:

Thêm các trường bắt buộc:

Chúng tôi không cần bất kỳ nhóm nào tại thời điểm này, vì vậy hãy tiếp tục bằng cách nhấp vào Tiếp theo :

Chọn Bố cục Định hướng của báo cáo dữ liệu:

Cuối cùng, thêm tiêu đề Bài báo cho mỗi báo cáo của tác giả và nhấp vào Hoàn tất :

Tiếp theo, điều chỉnh định dạng của báo cáo theo yêu cầu:

Nhấp vào Xem trước để xem báo cáo cơ sở dữ liệu:

Lưu báo cáo dưới dạng ArticlesPerAuthorReport . Báo cáo cơ sở dữ liệu đã được tạo do các yêu cầu kinh doanh.

Sử dụng Quy trình Thiết lập

Khi bạn viết các bài kiểm tra đơn vị cơ sở dữ liệu bằng tSQLt, bạn sẽ thấy rằng một số mã kiểm tra được lặp lại thường xuyên. Do đó, bạn có thể xác định nó trong một thủ tục thiết lập và sử dụng lại nó sau đó trong các bài kiểm tra đơn vị khác của lớp kiểm tra cụ thể đó. Mỗi lớp kiểm tra chỉ có thể có một quy trình thiết lập chạy tự động trước các quá trình kiểm tra đơn vị của lớp đó.

Chúng tôi có thể đặt hầu hết tất cả mã thử nghiệm được viết dưới Assemble (phần) trong quy trình thiết lập để tránh trùng lặp mã.

Ví dụ, chúng ta cần tạo các bảng giả cùng với một bảng dự kiến. Sau đó, chúng tôi sẽ thêm dữ liệu vào các bảng được chế tạo và sau đó vào bảng mong đợi. Chúng tôi có thể xác định nó một cách dễ dàng theo quy trình thiết lập và sử dụng lại nó.

Tạo Quy trình Thiết lập để tránh trùng lặp mã kiểm tra

Tạo thủ tục được lưu trữ trong SQLDevBlogTDD như sau:

-- (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

Bây giờ, hãy xóa mã kiểm tra mà chúng tôi đã viết trong quy trình thiết lập từ kiểm tra đơn vị trước đó để kiểm tra ArticlesPerAuthorReport kết quả đầu ra như sau:

-- (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.

Kết luận

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. T-SQL so với SQL

  2. UNION ALL Tối ưu hóa

  3. Prisma, cách xóa cơ sở dữ liệu

  4. Dỡ bỏ cơ sở dữ liệu rất lớn

  5. Kết nối Delphi với Salesforce.com