Kiểm thử liên tục với microservices (kèm ví dụ)


Khi nào thì Kiến trúc microservice là con đường để đi?

Việc lựa chọn và thiết kế kiến trúc chính xác cho một hệ thống là rất quan trọng. Người ta phải đảm bảo chất lượng của các yêu cầu dịch vụ và xử lý các yêu cầu phi chức năng, chẳng hạn như khả năng bảo trì, khả năng mở rộng và khả năng kiểm thử.

Kiến trúc microservice là một lựa chọn thường xuyên trong các hệ sinh thái mới nhất sau khi các công ty áp dụng Agile và DevOps. Mặc dù không phải là một lựa chọn trên thực tế, nhưng khi xử lý các hệ thống đang phát triển rộng rãi và khi kiến trúc nguyên khối không còn khả thi để duy trì, đây là một trong những lựa chọn ưu tiên. Việc giữ cho các thành phần được định hướng theo dịch vụ và được liên kết lỏng lẻo cho phép các chu kỳ phát triển và phát hành liên tục diễn ra liên tục. Điều này thúc đẩy các doanh nghiệp liên tục thử nghiệm và nâng cấp phần mềm của họ.

Các điều kiện tiên quyết chính đòi hỏi một kiến trúc như vậy là:

  • Thiết kế hướng tên miền
  • Giao hàng liên tục và văn hóa DevOps
  • Cách ly lỗi
  • Phân cấp

Nó có những lợi ích sau:

  • Quyền sở hữu nhóm
  • Phát hành thường xuyên
  • Bảo trì dễ dàng hơn
  • Dễ dàng nâng cấp lên phiên bản mới hơn
  • Công nghệ bất khả tri

Nó có những nhược điểm sau:

  • cơ chế giao tiếp giữa microservice với microservice
  • Việc tăng số lượng dịch vụ làm tăng độ phức tạp của toàn bộ hệ thống

Kiến trúc càng phân tán và phức tạp thì càng khó đảm bảo rằng hệ thống có thể được mở rộng và duy trì trong khi kiểm soát chi phí và rủi ro. Một giao dịch kinh doanh có thể liên quan đến nhiều sự kết hợp của các giao thức và công nghệ. Nó không chỉ là về các trường hợp sử dụng mà còn về hoạt động của nó. Khi áp dụng các phương pháp tiếp cận Agile và DevOps, người ta nên tìm sự cân bằng giữa tính linh hoạt và chức năng nhằm đạt được sự sửa đổi và thử nghiệm liên tục.

Tầm quan trọng của các chiến lược thử nghiệm liên quan đến vi dịch vụ

Việc áp dụng DevOps trong một tổ chức nhằm mục đích loại bỏ các bộ phận bị cô lập khác nhau và hướng tới một nhóm tổng thể. Động thái này nhằm mục đích cải thiện cụ thể các mối quan hệ và quy trình giữa nhóm phần mềm và nhóm vận hành. Cung cấp với tốc độ nhanh hơn cũng có nghĩa là đảm bảo rằng có quá trình thử nghiệm liên tục như một phần của quy trình phân phối phần mềm. Triển khai hàng ngày (và trong một số trường hợp thậm chí vài giờ một lần) là một trong những mục tiêu chính để cung cấp giải pháp kinh doanh toàn diện nhanh chóng. Độ tin cậy và bảo mật phải được ghi nhớ ở đây và đây là lúc thử nghiệm xuất hiện.

Việc đưa vào phát triển dựa trên thử nghiệm là cách duy nhất để đạt được niềm tin thực sự rằng mã đã sẵn sàng để sản xuất. Các trường hợp kiểm thử hợp lệ sẽ tăng thêm giá trị cho hệ thống vì chúng xác thực và ghi lại chính hệ thống đó. Ngoài ra, phạm vi bảo hiểm mã tốt sẽ khuyến khích cải tiến và hỗ trợ trong quá trình tái cấu trúc.

Kiến trúc microservice phân cấp các kênh liên lạc, khiến việc thử nghiệm trở nên phức tạp hơn. Đó không phải là một vấn đề không thể vượt qua. Nhóm sở hữu microservice không nên ngại đưa ra các thay đổi vì chúng có thể làm hỏng các ứng dụng khách hiện có. Kiểm tra thủ công rất kém hiệu quả, vì tích hợp liên tục và triển khai liên tục là phương pháp tốt nhất hiện nay. Các kỹ sư DevOps phải đảm bảo đưa các thử nghiệm tự động hóa vào quy trình phát triển của họ: viết thử nghiệm, thêm/tái cấu trúc mã và chạy thử nghiệm.

Các phương pháp kiểm tra microservice phổ biến

Kim tự tháp kiểm tra là một khái niệm dễ hiểu giúp chúng ta xác định nỗ lực cần thiết khi viết bài kiểm tra và số lượng bài kiểm tra sẽ giảm nếu độ chi tiết giảm. Nó cũng áp dụng khi xem xét thử nghiệm liên tục cho các vi dịch vụ.

Để làm cho chủ đề cụ thể hơn, chúng ta sẽ giải quyết việc thử nghiệm một vi dịch vụ mẫu bằng Spring Boot và Java. Về mặt cấu trúc, kiến trúc microservice phức tạp hơn kiến trúc nguyên khối. Tuy nhiên, chúng tôi sẽ tập trung vào loại thử nghiệm chứ không phải vào kiến trúc. Đoạn mã của chúng tôi dựa trên một dự án tối thiểu bao gồm một dịch vụ vi mô dựa trên API sở hữu kho dữ liệu sử dụng MongoDB.

Kiểm tra đơn vị

Các bài kiểm tra đơn vị phải là phần lớn các bài kiểm tra vì chúng nhanh, đáng tin cậy và dễ bảo trì. Những thử nghiệm này còn được gọi là thử nghiệm hộp trắng. Kỹ sư triển khai chúng đã quen với logic và đang viết bài kiểm thử để xác thực các thông số kỹ thuật của mô-đun và kiểm tra chất lượng mã.

Trọng tâm của các bài kiểm tra này là một phần nhỏ của hệ thống bị cô lập, tức là Lớp đang kiểm tra (CUT). Nguyên tắc Trách nhiệm duy nhất là hướng dẫn tốt về cách quản lý mã liên quan đến chức năng.

Hình thức phổ biến nhất của bài kiểm tra đơn vị là “bài kiểm tra đơn vị đơn lẻ”. ” Nó không vượt qua bất kỳ ranh giới nào và không cần bất kỳ cộng tác viên nào ngoài CUT.

Như Bill Caputo đã nêu, cơ sở dữ liệu, kênh nhắn tin hoặc các hệ thống khác là ranh giới; bất kỳ lớp bổ sung nào được CUT sử dụng hoặc yêu cầu đều là cộng tác viên. Một bài kiểm tra đơn vị không bao giờ được vượt qua một ranh giới. Khi sử dụng cộng tác viên, người ta đang viết “bài kiểm tra đơn vị hòa đồng. ” Sử dụng mô hình cho các phần phụ thuộc được CUT sử dụng là một cách để kiểm tra mã hòa đồng bằng “kiểm tra đơn vị đơn độc. ”

Trong các mô hình phát triển phần mềm truyền thống, thử nghiệm dành cho nhà phát triển vẫn chưa được áp dụng rộng rãi, việc thử nghiệm phải hoàn toàn không đồng bộ với quá trình phát triển. Việc đạt được xếp hạng về độ bao phủ mã cao được coi là chỉ số chính về độ tin cậy của bộ thử nghiệm.

Với sự ra đời của Agile và các chu kỳ lặp lại ngắn, rõ ràng là các mô hình thử nghiệm trước đây không còn hoạt động nữa. Những thay đổi thường xuyên được mong đợi liên tục. Điều quan trọng hơn nhiều là kiểm tra hành vi có thể quan sát được thay vì kiểm tra tất cả các đường dẫn mã. Kiểm thử đơn vị nên thiên về xác nhận hơn là phạm vi mã vì mục đích là xác minh rằng logic đang hoạt động như mong đợi.

Sẽ vô ích nếu có một thành phần có vô số thử nghiệm và tỷ lệ bao phủ mã cao khi các thử nghiệm không có xác nhận thích hợp. Việc áp dụng cách tiếp cận Phát triển theo hướng hành vi (BDD) nhiều hơn sẽ đảm bảo rằng các thử nghiệm đang xác minh trạng thái cuối và hành vi đó phù hợp với các yêu cầu do doanh nghiệp đặt ra. Ưu điểm của việc kiểm tra tập trung với phạm vi được xác định rõ ràng là việc xác định nguyên nhân thất bại trở nên dễ dàng hơn. Các thử nghiệm BDD giúp chúng tôi có độ tin cậy cao hơn rằng lỗi là kết quả của sự thay đổi trong hoạt động của tính năng. Mặt khác, các thử nghiệm tập trung nhiều hơn vào phạm vi mã không thể mang lại nhiều độ tin cậy vì sẽ có nguy cơ cao hơn rằng thất bại là hậu quả đối với những thay đổi được thực hiện trong chính các thử nghiệm do chi tiết triển khai đường dẫn mã.

Các thử nghiệm nên tuân theo gợi ý của Martin Fowler khi ông tuyên bố những điều sau (trong Tái cấu trúc: Cải thiện thiết kế mã hiện có, Ấn bản thứ hai. Kent Beck và Martin Fowler. Addison-Wesley. 2018):

Một lý do khác để ít tập trung hơn vào các chi tiết triển khai nhỏ là việc tái cấu trúc. Trong quá trình tái cấu trúc, nên có các bài kiểm tra đơn vị để mang lại cho chúng tôi sự tự tin và không làm chậm công việc. Một thay đổi trong việc triển khai cộng tác viên có thể dẫn đến lỗi thử nghiệm, điều này có thể khiến việc duy trì thử nghiệm trở nên khó khăn hơn. Rất khuyến khích giữ tối thiểu các bài kiểm tra đơn vị hòa đồng. Điều này đặc biệt đúng khi các thử nghiệm như vậy có thể làm chậm vòng đời phát triển và có khả năng các thử nghiệm cuối cùng sẽ bị bỏ qua. Một tình huống tuyệt vời để đưa vào bài kiểm tra đơn vị hòa đồng là kiểm tra tiêu cực, đặc biệt là khi xử lý việc xác minh hành vi.

Kiểm tra tích hợp

Một trong những thách thức quan trọng nhất với microservice là kiểm tra sự tương tác của chúng với phần còn lại của các dịch vụ cơ sở hạ tầng, tức là các ranh giới mà CUT cụ thể phụ thuộc vào, chẳng hạn như cơ sở dữ liệu hoặc các dịch vụ khác. Kim tự tháp kiểm tra cho thấy rõ ràng rằng các bài kiểm tra tích hợp phải ít hơn các bài kiểm tra đơn vị nhưng nhiều hơn các bài kiểm tra thành phần và từ đầu đến cuối. Các loại thử nghiệm khác này có thể chậm hơn, khó viết và bảo trì hơn và khá dễ hỏng khi so sánh với các thử nghiệm đơn vị. Việc vượt qua các ranh giới có thể có tác động đến hiệu suất và thời gian thực hiện do khả năng truy cập mạng và cơ sở dữ liệu; Tuy nhiên, chúng vẫn không thể thiếu, đặc biệt là trong văn hóa DevOps.

Trong phạm vi Triển khai liên tục, các thử nghiệm tích hợp hẹp được ưu tiên thay vì thử nghiệm tích hợp rộng. Loại thứ hai rất gần với các thử nghiệm từ đầu đến cuối trong đó nó yêu cầu dịch vụ thực tế chạy thay vì sử dụng thử nghiệm kép của các dịch vụ đó để kiểm tra các tương tác mã. Mục tiêu chính cần đạt được là xây dựng các thử nghiệm hoạt động có thể quản lý được một cách nhanh chóng, dễ dàng và linh hoạt. Kiểm tra tích hợp tập trung vào sự tương tác của CUT với một dịch vụ tại một thời điểm. Trọng tâm của chúng tôi là các bài kiểm tra tích hợp hẹp. Việc xác minh sự tương tác giữa một cặp dịch vụ có thể được xác nhận là như mong đợi, trong đó dịch vụ có thể là dịch vụ cơ sở hạ tầng hoặc bất kỳ dịch vụ nào khác.

Kiểm tra độ bền

>

Một loại thử nghiệm gây tranh cãi là khi thử nghiệm lớp lưu trữ lâu dài, với mục đích chính là kiểm tra các truy vấn và tác động lên dữ liệu thử nghiệm. Một lựa chọn là sử dụng cơ sở dữ liệu trong bộ nhớ. Một số người có thể coi việc sử dụng cơ sở dữ liệu trong bộ nhớ như một bài kiểm tra đơn vị hòa đồng vì đây là bài kiểm tra độc lập, bình thường và nhanh chóng. Thử nghiệm chạy dựa trên cơ sở dữ liệu được tạo với cấu hình mong muốn. Sau khi xác minh các lần chạy thử nghiệm và xác nhận, kho lưu trữ dữ liệu sẽ tự động bị xóa sau khi JVM thoát do tính chất phù du của nó. Hãy nhớ rằng vẫn có kết nối xảy ra với một dịch vụ khác và được coi là thử nghiệm tích hợp hẹp. Theo cách tiếp cận Phát triển dựa trên thử nghiệm (TDD), các thử nghiệm như vậy rất cần thiết vì bộ thử nghiệm sẽ chạy trong vòng vài giây. Cơ sở dữ liệu trong bộ nhớ là một sự đánh đổi hợp lệ để đảm bảo rằng các bài kiểm tra được lưu giữ nhanh nhất có thể và không bị bỏ qua về lâu dài.

@Before
public void setup() throws Exception {
   try {
	// this will download the version of mongo marked as production. One should
	// always mention the version that is currently being used by the SUT
	String ip = "localhost";
	int port = 27017;

	IMongodConfig mongodConfig = new MongodConfigBuilder().version(Version.Main. PRODUCTION)
		.net(new Net(ip, port, Network.localhostIsIPv6())).build();

	MongodStarter starter = MongodStarter.getDefaultInstance();
mongodExecutable = starter.prepare(mongodConfig);
	mongodExecutable.start();

   } catch (IOException e) {
	e.printStackTrace();
   }
}

Đoạn 1: Cài đặt và khởi động MongoDB trong bộ nhớ

Ở trên không phải là thử nghiệm tích hợp đầy đủ vì cơ sở dữ liệu trong bộ nhớ không hoạt động chính xác như máy chủ cơ sở dữ liệu sản xuất. Do đó, nó không phải là bản sao cho máy chủ mongo “thực”, điều này sẽ xảy ra nếu người ta chọn thử nghiệm tích hợp rộng rãi.

Một tùy chọn khác cho các thử nghiệm tích hợp liên tục là chạy các thử nghiệm rộng rãi được kết nối với máy chủ cơ sở dữ liệu thực tế hoặc bằng cách sử dụng các vùng chứa. Các vùng chứa giúp giảm bớt khó khăn vì theo yêu cầu, người ta sẽ cung cấp cơ sở dữ liệu so với việc có một máy chủ cố định. Hãy nhớ rằng các bài kiểm tra như vậy rất tốn thời gian và việc phân loại các bài kiểm tra là một giải pháp khả thi. Vì các thử nghiệm này phụ thuộc vào một dịch vụ khác chạy ngoài CUT nên nó được coi là thử nghiệm hệ thống. Những thử nghiệm này vẫn rất cần thiết và bằng cách sử dụng các danh mục, người ta có thể xác định rõ hơn thời điểm nên chạy thử nghiệm cụ thể để có được sự cân bằng tốt nhất giữa chi phí và giá trị. Ví dụ: trong chu kỳ phát triển, người ta có thể chỉ chạy các thử nghiệm tích hợp hẹp bằng cách sử dụng cơ sở dữ liệu trong bộ nhớ. Các bản dựng hàng đêm cũng có thể chạy thử nghiệm thuộc danh mục chẳng hạn như thử nghiệm tích hợp rộng.

@Category(FastIntegration.class)
@RunWith(SpringRunner.class)
@DataMongoTest
public class DailyTaskRepositoryInMemoryIntegrationTest {
	. . . 
}

@Category(SlowIntegration.class)
@RunWith(SpringRunner.class)
@DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class)
public class DailyTaskRepositoryIntegrationTest {
   ...
}

Đoạn 2: Sử dụng danh mục để phân biệt các loại thử nghiệm tích hợp

Thử nghiệm hướng tới người tiêu dùng

Cơ chế Giao tiếp giữa các quá trình (IPC) là một khía cạnh trung tâm của các hệ thống phân tán dựa trên kiến trúc microservice. Thiết lập này gây ra nhiều vấn đề phức tạp trong quá trình tạo bộ thử nghiệm. Ngoài ra, trong nhóm Agile, các thay đổi liên tục được thực hiện, bao gồm cả những thay đổi về API hoặc sự kiện. Bất kể hệ thống đang sử dụng cơ chế IPC nào, đều có sự hiện diện của hợp đồng giữa hai dịch vụ bất kỳ. Có nhiều loại hợp đồng khác nhau, tùy thuộc vào cơ chế nào người ta chọn sử dụng trong hệ thống. Khi sử dụng API, hợp đồng là yêu cầu và phản hồi HTTP, trong khi trong trường hợp hệ thống dựa trên sự kiện, hợp đồng là chính sự kiện miền.

Mục tiêu chính khi thử nghiệm microservice là đảm bảo các hợp đồng đó được xác định rõ ràng và ổn định tại bất kỳ thời điểm nào. Trong cách tiếp cận TDD từ trên xuống, đây là những thử nghiệm đầu tiên được đề cập. Thử nghiệm tích hợp cơ bản đảm bảo rằng người tiêu dùng có phản hồi nhanh chóng ngay khi khách hàng không khớp với trạng thái thực tế của nhà sản xuất mà họ đang nói chuyện.

Những thử nghiệm này phải là một phần của quy trình triển khai thường xuyên. Thất bại của họ sẽ cho phép người tiêu dùng nhận thức được rằng đã có sự thay đổi từ phía nhà sản xuất và những thay đổi đó là cần thiết để đạt được sự nhất quán một lần nữa. Không cần phải viết các bài kiểm thử phức tạp từ đầu đến cuối, 'thử nghiệm theo hợp đồng do người tiêu dùng định hướng' sẽ nhắm đến trường hợp sử dụng này.

Sau đây là mẫu trình xác minh hợp đồng được tạo bởi plugin hợp đồng mùa xuân-cloud.

@Test
public void validate_add_New_Task() throws Exception {
  // given:
   MockMvcRequestSpecification request = given()
.header("Content-Type", "application/json;charset=UTF-8")
	.body("{"taskName":"newTask","taskDescription":"newDescription","isComplete":false,"isUrgent":true}");

  // when:
   ResponseOptions response = given().spec(request).post("/tasks");

  // then:
   assertThat(response.statusCode()).isEqualTo(200);
   assertThat(response.header("Content-Type")).isEqualTo("application/json;charset=UTF-8");
  // and:
   DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
   assertThatJson(parsedJson).field("['taskName']").isEqualTo("newTask");
   assertThatJson(parsedJson).field("['isUrgent']").isEqualTo(true);
   assertThatJson(parsedJson).field("['isComplete']").isEqualTo(false);
   assertThatJson(parsedJson).field("['id']").isEqualTo("3");
   assertThatJson(parsedJson).field("['taskDescription']").isEqualTo("newDescription");
}

Đoạn mã 3: Trình xác minh hợp đồng được tạo tự động bởi plugin hợp đồng mùa xuân-cloud

Một BaseClass được viết trong trình sản xuất sẽ hướng dẫn loại phản hồi mong đợi đối với các loại yêu cầu khác nhau bằng cách sử dụng thiết lập độc lập. Bộ sưu tập sơ khai được đóng gói có sẵn cho tất cả người tiêu dùng để có thể lôi kéo họ thực hiện. Sự phức tạp phát sinh khi nhiều người tiêu dùng sử dụng cùng một hợp đồng; do đó, nhà sản xuất cần có cái nhìn tổng thể về các hợp đồng dịch vụ được yêu cầu.

@RunWith(SpringRunner.class)
@SpringBootTest
public class ContractBaseClass {

	@Autowired
	private DailyTaskController taskController;

	@MockBean
	private DailyTaskRepository dailyTaskRepository;

	@Before
	public void before() {
		RestAssuredMockMvc.standaloneSetup(this.taskController);
		Mockito.when(this.dailyTaskRepository.findById("1")).thenReturn(
Optional.of(new DailyTask("1", "Test", "Description", false, null)));
		
		. . . 
				
		Mockito.when(this.dailyTaskRepository.save(
new DailyTask(null, "newTask", "newDescription", false, true))).thenReturn(
new DailyTask("3", "newTask", "newDescription", false, true));
		
	}

Đoạn 4: BaseClass của nhà sản xuất xác định phản hồi dự kiến cho mỗi yêu cầu

Về phía người tiêu dùng, với việc bao gồm phần phụ thuộc spring-cloud-starter-contract-stub-runner, chúng tôi đã định cấu hình thử nghiệm để sử dụng tệp nhị phân sơ khai. Thử nghiệm này sẽ chạy bằng cách sử dụng các sơ khai do nhà sản xuất tạo theo cấu hình có phiên bản được chỉ định hoặc luôn là phiên bản mới nhất. Tạo tác sơ khai liên kết khách hàng với nhà sản xuất để đảm bảo rằng cả hai đều đang làm việc trên cùng một hợp đồng. Bất kỳ thay đổi nào xảy ra sẽ phản ánh trong các thử nghiệm đó và do đó, người tiêu dùng sẽ xác định liệu nhà sản xuất có thay đổi hay không.

@SpringBootTest(classes = TodayAskApplication.class)
@RunWith(SpringRunner.class)
@AutoConfigureStubRunner(ids = "com.cwie.arch:today:+:stubs:8080", stubsMode = StubRunnerProperties.StubsMode.LOCAL)
public class TodayClientStubTest {
 	 . . .
	@Test
	public void addTask_expectNewTaskResponse () {
		Task newTask = todayClient.createTask(
new Task(null, "newTask", "newDescription", false, true));
		BDDAssertions.then(newTask).isNotNull();
		BDDAssertions.then(newTask.getId()).isEqualTo("3");
		. . . 
		
	}
}

Đoạn 5: Người tiêu dùng đưa vào phiên bản sơ khai do nhà sản xuất xác định

Các thử nghiệm tích hợp như vậy xác minh rằng API của nhà cung cấp vẫn phù hợp với mong đợi của người tiêu dùng. Khi sử dụng các thử nghiệm đơn vị mô phỏng cho API, chúng tôi sẽ đặt các API sơ khai và mô phỏng hành vi. Từ quan điểm của người tiêu dùng, những loại thử nghiệm này sẽ đảm bảo rằng khách hàng đáp ứng được mong đợi của chúng tôi. Điều cần lưu ý là nếu phía nhà sản xuất thay đổi API thì những thử nghiệm đó sẽ không thất bại. Và điều bắt buộc là phải xác định nội dung bài kiểm tra bao gồm.

// the response we expect is represented in the task1.json file
private Resource taskOne = new ClassPathResource("task1.json");

@Autowired
private TodayClient todayClient;

@Test
public void createNewTask_expectTaskIsCreated() {
WireMock.stubFor(WireMock.post(WireMock.urlMatching("/tasks"))
		.willReturn(WireMock.aResponse()
		.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE)
		.withStatus(HttpStatus.OK.value())
		.withBody(transformResourceJsonToString(taskOne))));
		
	Task tasks = todayClient.createTask(new Task(null, "runUTest", "Run Test", false, true));
	BDDAssertions.then(tasks.getId()).isEqualTo("1");

Đoạn trích 6: Thử nghiệm của người tiêu dùng thực hiện các xác nhận dựa trên phản hồi được xác định của chính nó

Kiểm tra thành phần

Kiến trúc microservice có thể phát triển nhanh chóng và do đó thành phần được thử nghiệm có thể được tích hợp với nhiều thành phần khác và nhiều dịch vụ cơ sở hạ tầng. Cho đến thời điểm hiện tại, chúng tôi đã đề cập đến thử nghiệm hộp trắng bằng các thử nghiệm đơn vị và thử nghiệm tích hợp hẹp để kiểm tra CUT vượt qua ranh giới để tích hợp với dịch vụ khác.

Loại thử nghiệm thành phần nhanh nhất là phương pháp tiếp cận trong quá trình, trong đó, cùng với việc sử dụng các phép thử kép và kho dữ liệu trong bộ nhớ, việc thử nghiệm vẫn nằm trong giới hạn. Nhược điểm chính của phương pháp này là dịch vụ sản xuất có thể triển khai không được kiểm tra đầy đủ; ngược lại, thành phần này yêu cầu những thay đổi để kết nối ứng dụng một cách khác nhau. Phương pháp ưa thích là thử nghiệm thành phần ngoài quy trình. Đây giống như các thử nghiệm đầu cuối, nhưng với tất cả các cộng tác viên bên ngoài được thay đổi bằng thử nghiệm nhân đôi, bằng cách đó, nó thực hiện tạo phẩm được triển khai đầy đủ bằng cách sử dụng các lệnh gọi mạng thực. Quá trình kiểm tra sẽ chịu trách nhiệm định cấu hình chính xác mọi dịch vụ bên ngoài dưới dạng sơ khai.

@Ignore
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { TodayConfiguration.class, TodayIntegrationApplication.class,
   CloudFoundryClientConfiguration.class })
public class BaseFunctionalitySteps {

   @Autowired
   private CloudFoundryOperations cf;

   private static File manifest = new File(".manifest.yml");

   @Autowired
   private TodayClient client;

   // Any stubs required 
   . . . 

   public void setup() {

cf.applications().pushManifest(PushApplicationManifestRequest.builder() 
 
 .manifest(ApplicationManifestUtils.read(manifest.toPath()).get(0)).build()).block();
}
. . .
// Any calls required by tests
public void requestForAllTasks() {
this.client.getTodoTasks();
}
}

Đoạn mã 7: Triển khai tệp kê khai trên CloudFoundry và mọi lệnh gọi mà quá trình kiểm tra yêu cầu

Cloud Foundry là một trong những tùy chọn được sử dụng cho kiến trúc thử nghiệm dựa trên vùng chứa. “Đây là nền tảng ứng dụng đám mây nguồn mở giúp việc xây dựng, thử nghiệm, triển khai và mở rộng quy mô ứng dụng nhanh hơn và dễ dàng hơn. ” Sau đây là manifest.yml, một tệp xác định cấu hình của tất cả các ứng dụng trong hệ thống. Tệp này được sử dụng để triển khai dịch vụ thực tế ở định dạng sẵn sàng sản xuất trên không gian của tổ chức Pivotal nơi dịch vụ MongoDB đã được thiết lập, phù hợp với phiên bản sản xuất.

---
applications:
- name: today
  instances: 1
  path: ../today/target/today-0.0.1-SNAPSHOT.jar 
  memory: 1024M
  routes:
  - route: today.cfapps.io
  services:
  - mongo-it

Đoạn 8: Triển khai một phiên bản của dịch vụ tùy thuộc vào dịch vụ mongo

Khi chọn phương pháp ngoài quy trình, hãy nhớ rằng các ranh giới thực tế đang được thử nghiệm và do đó, các thử nghiệm sẽ chậm hơn do có các tương tác mạng và cơ sở dữ liệu. Sẽ là lý tưởng nếu các bộ thử nghiệm đó được viết trong một mô-đun riêng biệt. Để có thể chạy chúng riêng biệt ở giai đoạn maven khác thay vì giai đoạn 'thử nghiệm' thông thường.

Vì trọng tâm của các thử nghiệm là vào chính thành phần đó nên các thử nghiệm bao gồm các trách nhiệm chính của thành phần đó trong khi cố tình bỏ qua bất kỳ phần nào khác của hệ thống.

Dưa chuột, một công cụ phần mềm hỗ trợ Phát triển theo hướng hành vi, là một tùy chọn để xác định các bài kiểm tra hành vi như vậy. Với trình phân tích cú pháp ngôn ngữ đơn giản, Gherkin, nó đảm bảo rằng khách hàng có thể dễ dàng hiểu tất cả các bài kiểm tra được mô tả. Tệp tính năng Cucumber sau đây đảm bảo rằng việc triển khai thành phần của chúng tôi phù hợp với các yêu cầu kinh doanh cho tính năng cụ thể đó.

Feature: Tasks

Scenario: Retrieving one task from list
 Given the component is running
 And the data consists of one or more tasks
 When user requests for task x
 Then the correct task x is returned

Scenario: Retrieving all lists
 Given the data consists of one or more tasks
 When user requests for all tasks
 Then all tasks in database are returned

Scenario: Negative Test
 Given the component is not running
 When user requests for task x it fails with response 404

Đoạn 9: Tệp tính năng xác định các bài kiểm tra BDD

Kiểm tra đầu cuối

Tương tự như kiểm thử thành phần, mục đích của các kiểm thử toàn diện này không phải là thực hiện phạm vi bao phủ mã mà là để đảm bảo rằng hệ thống đáp ứng các tình huống kinh doanh được yêu cầu. Sự khác biệt là trong thử nghiệm từ đầu đến cuối, tất cả các thành phần đều hoạt động trong quá trình thử nghiệm.

Theo sơ đồ kim tự tháp thử nghiệm, số lượng thử nghiệm từ đầu đến cuối giảm hơn nữa, có tính đến sự chậm chạp mà chúng có thể gây ra. Bước đầu tiên là chạy thiết lập và trong ví dụ này, chúng tôi sẽ tận dụng docker.

version: '3.7'
services:
    today-app:
        image: today-app:1
        container_name: "today-app"
        build:
          context: ./
          dockerfile: DockerFile
        environment:
           - SPRING_DATA_MONGODB_HOST=mongodb
        volumes:
          - /data/today-app
        ports:
          - "8082:8080"
        links:
          - mongodb
        depends_on:
          - mongodb

    mongodb:
        image: mongo:3.2
        container_name: "mongodb"
        restart: always
        environment:
           - AUTH=no
           - MONGO_DATA_DIR=/data/db
           - MONGO_LOG_DIR=/dev/log
        volumes:
           - ./data:/data
        ports:
           - 27017:27017
        command: mongod --smallfiles --logpath=/dev/null # --quiet

Đoạn mã 10: Định nghĩa docker.yml được sử dụng để triển khai dịch vụ được xác định và phiên bản mongo được chỉ định dưới dạng vùng chứa

Theo các thử nghiệm thành phần, việc giữ các thử nghiệm đầu cuối trong một mô-đun riêng biệt và các giai đoạn khác nhau là điều hợp lý. exec-maven-plugin được sử dụng để triển khai tất cả các thành phần cần thiết, thực hiện các thử nghiệm và cuối cùng là làm sạch và phá bỏ môi trường thử nghiệm của chúng tôi.

Vì đây là thử nghiệm ngăn xếp rộng nên sẽ thực thi một lựa chọn thử nghiệm nhỏ hơn cho mỗi tính năng. Các thử nghiệm được lựa chọn dựa trên rủi ro kinh doanh được nhận thức. Các loại thử nghiệm trước đây bao gồm các chi tiết cấp thấp. Điều đó có nghĩa là liệu câu chuyện của người dùng có phù hợp với Tiêu chí chấp nhận hay không. Các thử nghiệm này cũng sẽ ngay lập tức dừng phát hành vì lỗi ở đây có thể gây ra hậu quả nghiêm trọng cho hoạt động kinh doanh.

Phần kết luận

Thử nghiệm tập trung vào bàn giao thường kết thúc bằng một quá trình rất dài, mất tới vài tuần cho đến khi tất cả các lỗi được xác định, sửa chữa và triển khai mới sẵn sàng. Phản hồi chỉ được nhận sau khi bản phát hành được thực hiện, giúp thời gian tồn tại của phiên bản trở nên nhanh nhất có thể.

Phương pháp thử nghiệm liên tục đảm bảo phản hồi ngay lập tức. Có nghĩa là kỹ sư DevOps sẽ ngay lập tức biết liệu tính năng được triển khai đã sẵn sàng để đưa vào sản xuất hay chưa, tùy thuộc vào kết quả của quá trình chạy thử nghiệm. Từ các bài kiểm tra đơn vị cho đến các bài kiểm tra đầu cuối, tất cả đều hỗ trợ đẩy nhanh quá trình đánh giá.

Kiến trúc vi dịch vụ giúp triển khai sản xuất nhanh hơn vì nó được điều khiển theo miền. Nó đảm bảo cách ly lỗi và tăng quyền sở hữu. Khi nhiều nhóm làm việc trên cùng một dự án, đó là một lý do khác để áp dụng kiến trúc như vậy: Để đảm bảo rằng các nhóm độc lập và không can thiệp vào công việc của nhau.

Cải thiện khả năng kiểm tra bằng cách tiến tới thử nghiệm liên tục. Mỗi microservice có một miền được xác định rõ ràng và phạm vi của nó phải được giới hạn ở một tác nhân. Các trường hợp thử nghiệm được áp dụng cụ thể và ngắn gọn hơn, đồng thời các thử nghiệm được tách biệt, tạo điều kiện cho việc phát hành và triển khai nhanh hơn.

Theo cách tiếp cận TDD, không có mã hóa trừ khi kết quả kiểm tra thất bại trở lại. Quá trình này làm tăng độ tin cậy khi việc triển khai lặp lại dẫn đến thử nghiệm thành công. Quá trình này ngụ ý rằng thử nghiệm diễn ra song song với việc triển khai thực tế và tất cả các thử nghiệm được đề cập ở trên đều được thực hiện trước khi các thay đổi đến môi trường thử nghiệm. Thử nghiệm liên tục tiếp tục phát triển cho đến khi bước vào giai đoạn phát hành tiếp theo, tức là môi trường chạy thử, trong đó trọng tâm chuyển sang thử nghiệm toàn diện hơn chẳng hạn như thử nghiệm tải.

Agile, DevOps và phân phối liên tục yêu cầu thử nghiệm liên tục. Lợi ích chính là phản hồi ngay lập tức được tạo ra từ các thử nghiệm tự động. Những hậu quả có thể xảy ra có thể ảnh hưởng đến trải nghiệm người dùng nhưng cũng gây ra hậu quả kinh doanh có rủi ro cao. Để biết thêm thông tin về thử nghiệm liên tục, hãy liên hệ với phoenixNAP ngay hôm nay.

Bài viết liên quan