Nhà cung cấp dữ liệu phpunit

Viết bài kiểm tra cho các ứng dụng trong thế giới thực có thể lộn xộn. ý định của chúng tôi là tốt. chúng tôi viết một vài bài kiểm tra để giải quyết các trường hợp cạnh của chúng tôi, nhưng chúng tôi sớm nhận thấy logic rất giống nhau được lặp lại trong mỗi bài kiểm tra chỉ có sự khác biệt nhỏ trong dữ liệu thiết lập. Có thể chúng tôi đang thử nghiệm xác thực đầu vào của biểu mẫu hoặc triển khai các đối tượng khác nhau chia sẻ cùng một hợp đồng. May mắn thay, PHPUnit cung cấp cho chúng tôi một cách để củng cố logic chung này trong khi thay đổi dữ liệu thiết lập của chúng tôi mà không làm mất đi lợi ích của các phương pháp thử nghiệm chuyên dụng, nhỏ hơn. Trong bài đăng này, chúng ta sẽ khám phá PHPUnit's. Mặc dù các nhà cung cấp dữ liệu có sẵn trong bất kỳ bộ kiểm tra PHPUnit nào, hãy xem cách họ có thể giúp chúng tôi sắp xếp các kiểm tra của mình trong ứng dụng Laravel

Nhà cung cấp dữ liệu PHPUnit

Nhà cung cấp dữ liệu cho phép chúng tôi xác định các bài kiểm tra một lần và chạy chúng nhiều lần với các bộ dữ liệu khác nhau. Sử dụng nhà cung cấp dữ liệu yêu cầu ba bước

  1. Xác định một phương thức công khai trả về một mảng các bộ dữ liệu sẽ được sử dụng
  2. Chú thích nhà cung cấp dữ liệu trong khối tài liệu của bài kiểm tra của bạn
  3. Truyền tập dữ liệu làm đối số cho phương thức kiểm tra

* @dataProvider myTestProvider

public function we_are_testing_something_good_here[$dataProvider]

public function myTestProvider[]

Thử nghiệm này sẽ được thực hiện ba lần, lần đầu tiên

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

3 sẽ bằng '

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

0', lần thứ hai '

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

1' và lần thứ ba '

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

2'

Hãy xem xét một số cách sử dụng nhà cung cấp dữ liệu trong thế giới thực để hiểu rõ hơn cách họ có thể giúp làm gọn các thử nghiệm của chúng ta

Xác thực biểu mẫu

Giả sử chúng ta có một điểm cuối biểu mẫu với một số đầu vào bắt buộc và chúng tôi muốn kiểm tra xem ứng dụng của chúng ta có yêu cầu từng đầu vào không. Nếu biểu mẫu của chúng tôi có ba đầu vào, thông thường chúng tôi sẽ cần ba bài kiểm tra để bao gồm tất cả. Sử dụng các nhà cung cấp dữ liệu, thay vào đó, chúng tôi có thể xác định một thử nghiệm duy nhất để xác minh rằng tất cả ba yếu tố đầu vào trong biểu mẫu của chúng tôi đều được yêu cầu

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

3 định nghĩa ba bộ dữ liệu. Trong trường hợp này, giá trị của mỗi bộ dữ liệu tương ứng với giá trị

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

4 của đầu vào được kiểm tra. Ba bộ dữ liệu này sẽ chạy thử nghiệm

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

5 ba lần, một lần cho mỗi đầu vào

Chúng tôi cũng có thể sử dụng nhà cung cấp dữ liệu để kiểm tra nhiều quy tắc xác thực—ví dụ: bắt buộc phải có

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

4,

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

7 và

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

8, nhưng thông tin đầu vào

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

8 cũng phải ở định dạng email hợp lệ. May mắn thay, các nhà cung cấp dữ liệu cho phép chúng tôi xác định nhiều giá trị cho mỗi tập dữ liệu và cho phép chúng tôi truy cập vào các giá trị này trong các thử nghiệm của mình bằng cách thêm các đối số phương pháp thử nghiệm bổ sung

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

2

Giờ đây, nhà cung cấp dữ liệu của chúng tôi sẽ cho phép chúng tôi kiểm tra tất cả bốn quy tắc xác thực bằng một lần kiểm tra. Giống như trong ví dụ trước, bộ dữ liệu của nhà cung cấp khiến thử nghiệm

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

20 được chạy bốn lần, một lần cho mỗi bộ dữ liệu

Một điều bạn sẽ nhanh chóng nhận thấy khi sử dụng nhà cung cấp dữ liệu là đầu ra của các lần kiểm tra không thành công đã thay đổi. Khi thử nghiệm với nhà cung cấp dữ liệu không thành công, thông báo lỗi bao gồm chỉ mục số của tập dữ liệu không thành công, cùng với các giá trị gây ra lỗi

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

4

Đây không phải là thông báo lỗi mô tả nhất. May mắn thay, PHPUnit cho phép chúng tôi đặt một mã định danh mang tính mô tả hơn chỉ bằng cách xác định khóa mảng cho mỗi bộ dữ liệu của chúng tôi

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

5

Giờ đây, khi thử nghiệm sử dụng nhà cung cấp này không thành công, chúng tôi sẽ nhận được mô tả rõ ràng về tập dữ liệu chịu trách nhiệm

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

6

Kết quả thử nghiệm của chúng tôi đang trở nên tốt hơn, nhưng chúng tôi vẫn chưa có cách rõ ràng để xác định những lĩnh vực mà chúng tôi đang thử nghiệm chỉ bằng một cái nhìn lướt qua thử nghiệm của chúng tôi. Sẽ thật tuyệt nếu chúng ta có thể xem danh sách tất cả các lĩnh vực chúng ta định kiểm tra mà không cần phải đi sâu vào mảng nhà cung cấp. Một lần nữa, điều này có thể giải quyết được với rất ít nỗ lực từ phía chúng tôi, bằng cách xác định một nhà cung cấp dữ liệu riêng cho từng đầu vào. Chúng tôi sẽ cung cấp cho mỗi nhà cung cấp một tên mô tả để chúng tôi hiểu rõ hơn về nội dung của nó và kích hoạt tất cả chúng bằng cách thêm các ký hiệu

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

21 bổ sung vào thử nghiệm của chúng tôi

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

8

Kiểm tra triển khai đối tượng

Giả sử chúng tôi đã thiết kế một ứng dụng cho phép người dùng lập hóa đơn cho khách hàng bằng bộ xử lý thanh toán mà họ chọn [e. g. Sọc, Hình vuông hoặc Braintree]. Chúng tôi muốn có thể kiểm tra các hành động phổ biến trên từng đối tượng bộ xử lý [

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

22,

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

23]. Chúng ta có thể tạo một lớp kiểm tra cho từng đối tượng bộ xử lý [

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

24,

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

25, v.v.] và sao chép các kiểm tra cho từng hành động;

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

4

Bây giờ chúng tôi đã viết một lớp kiểm tra duy nhất chịu trách nhiệm kiểm tra từng đối tượng của bộ xử lý của chúng tôi với cùng một logic. Vì chúng tôi chỉ có một lớp thử nghiệm và một thử nghiệm cho từng hành động mà đối tượng bộ xử lý sẽ hỗ trợ, nên chúng tôi đảm bảo chắc chắn hơn rằng tất cả các đối tượng này sẽ được kiểm tra chính xác theo cùng một cách. Chúng tôi cũng đã giảm khả năng sai lệch giữa các thử nghiệm có thể xảy ra nếu chúng tôi chia chúng thành nhiều tệp và thực hiện việc thêm các thử nghiệm cho bộ xử lý mới đơn giản như thêm 1 dòng mã vào nhà cung cấp dữ liệu của chúng tôi

báo trước

Có một vấn đề cần xem xét khi sử dụng các nhà cung cấp dữ liệu của PHPUnit

Người chạy thử nghiệm xây dựng một bộ thử nghiệm bằng cách quét tất cả các thư mục thử nghiệm của bạn và xác định các lớp thử nghiệm và phương pháp thử nghiệm trong các lớp đó. Trong quá trình này, khi người chạy thử nghiệm xác định các phương pháp thử nghiệm [có chứa

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

27 trong tên phương pháp hoặc chú thích

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

28], người chạy thử nghiệm sẽ đánh giá bất kỳ chú thích

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

21 nào. Khi tìm thấy chú thích

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

21, nhà cung cấp dữ liệu được tham chiếu được THỰC HIỆN, sau đó một TestCase được tạo và thêm vào TestSuite cho từng tập dữ liệu trong nhà cung cấp

Đây là chà

Đầu tiên, nếu bạn sử dụng các phương thức xuất xưởng trong nhà cung cấp dữ liệu của mình, các nhà cung cấp dữ liệu này sẽ chạy một lần cho mỗi thử nghiệm sử dụng nhà cung cấp dữ liệu này TRƯỚC KHI thử nghiệm đầu tiên của bạn chạy. Vì vậy, một nhà cung cấp dữ liệu có tập dữ liệu phức tạp [ví dụ, yêu cầu tồn tại nhiều bản ghi cơ sở dữ liệu] được sử dụng bởi mười thử nghiệm sẽ chạy mười lần trước khi thử nghiệm đầu tiên của bạn chạy. Điều này có thể làm chậm đáng kể thời gian cho đến khi thử nghiệm đầu tiên của bạn thực hiện. Ngay cả khi bạn chạy một thử nghiệm bằng cách sử dụng

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

41, mọi nhà cung cấp dữ liệu sẽ vẫn chạy nhiều lần. Lọc xảy ra sau khi bộ thử nghiệm đã được tạo và do đó sau khi bất kỳ nhà cung cấp dữ liệu nào đã được thực thi

Thứ hai, Laravel tự khởi động trong phương thức

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

42 của PHPUnit. Điều này có nghĩa là ngoài hộp, chúng tôi không thể sử dụng bộ chứa ứng dụng, mặt tiền hoặc bất kỳ tiện ích nào khác của Laravel trong nhà cung cấp dữ liệu của chúng tôi nếu chúng phụ thuộc vào phiên bản ứng dụng/bộ chứa có sẵn. Nếu bạn cố gắng sử dụng một tính năng của Laravel trong nhà cung cấp dữ liệu của mình, các thử nghiệm triển khai tính năng đó sẽ không thực thi và bạn sẽ nhận được thông báo

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

43

May mắn thay, chúng ta cũng có thể giải quyết vấn đề này. Bằng cách trả lại một bao đóng từ tập dữ liệu của chúng tôi và gọi nó ở đầu phương thức thử nghiệm của chúng tôi, Laravel sẽ có cơ hội tải ứng dụng trước khi bất kỳ mã nào trong nhà cung cấp dữ liệu của chúng tôi được thực thi. Bây giờ chúng ta có thể dựa vào các phương thức xuất xưởng và chúng sẽ không tấn công cơ sở dữ liệu cho đến khi thử nghiệm của chúng ta được chạy

Hãy sửa đổi ví dụ của chúng tôi một chút bằng cách giả sử Bộ xử lý thanh toán của chúng tôi cần được giải quyết từ vùng chứa

* @dataProvider clientFormValidationProvider

public function required_inputs_are_required[$formInput]

$response = $this->json['POST', route['client.store', [

$response->assertStatus[422];

$response->assertJsonValidationErrors[$formInput];

public function clientFormValidationProvider[]

2

Phần kết luận

Các nhà cung cấp dữ liệu có thể giúp DRY bộ thử nghiệm của bạn và giảm nợ trực quan. Như với bất kỳ thứ gì, việc sử dụng chúng đi kèm với sự đánh đổi, nhưng khi được triển khai cẩn thận, chúng có thể tăng thêm giá trị và giúp các bộ thử nghiệm của bạn khơi dậy niềm vui

Chủ Đề