Đặt tên gói phù hợp để thử nghiệm với ngôn ngữ Go


102

Tôi đã thấy một số chiến lược đặt tên gói thử nghiệm khác nhau trong Go và muốn biết ưu nhược điểm của từng loại và tôi nên sử dụng chiến lược nào.

Chiến lược 1:

Tên tệp: github.com/user/myfunc.go

package myfunc

Tên tệp kiểm tra: github.com/user/myfunc_test.go

package myfunc

Xem bzip2 để làm ví dụ.

Chiến lược 2:

Tên tệp: github.com/user/myfunc.go

package myfunc

Tên tệp kiểm tra: github.com/user/myfunc_test.go

package myfunc_test

import (
    "github.com/user/myfunc"
)

Xem dây để làm ví dụ.

Chiến lược 3:

Tên tệp: github.com/user/myfunc.go

package myfunc

Tên tệp kiểm tra: github.com/user/myfunc_test.go

package myfunc_test

import (
    . "myfunc"
)

Xem chuỗi để làm ví dụ.

Thư viện tiêu chuẩn cờ vây dường như sử dụng hỗn hợp chiến lược 1 và 2. Tôi nên sử dụng chiến lược nào trong cả ba? Đó là một nỗi đau liên quan package *_testđến các gói thử nghiệm của tôi vì nó có nghĩa là tôi không thể kiểm tra các phương pháp riêng tư của gói nhưng có thể có một lợi thế ẩn mà tôi không biết?


9
Câu hỏi này sẽ chỉ dẫn đến nhiều ý kiến ​​khác nhau, nhưng tôi sẽ trả lời. Bạn không cần phải kiểm tra các phương pháp riêng tư của mình. Bạn muốn kiểm tra giao diện gói của mình mà các nhà phát triển khác sẽ sử dụng. Nếu các thử nghiệm không thành công thì bạn biết rằng các phương pháp riêng tư của bạn cần được xem xét.
Brenden

2
Các [dây] ( github.com/btcsuite/btcd/blob/master/wire/msgtx_test.go ) ví dụ cho Chiến lược 2, thực sự là bây giờ cũng là một ví dụ về chiến lược 1 ...
durp

Câu trả lời:


130

Sự khác biệt cơ bản giữa ba chiến lược bạn đã liệt kê là liệu mã kiểm tra có nằm trong cùng một gói với mã đang kiểm tra hay không. Quyết định sử dụng package myfunchoặc package myfunc_testtrong tệp thử nghiệm phụ thuộc vào việc bạn muốn thực hiện thử nghiệm hộp trắng hay hộp đen .

Không có gì sai khi sử dụng cả hai phương pháp trong một dự án. Ví dụ, bạn có thể có myfunc_whitebox_test.gomyfunx_blackbox_test.go.

So sánh gói mã thử nghiệm

  • Kiểm tra hộp đen: Sử dụng package myfunc_test, điều này sẽ đảm bảo bạn chỉ sử dụng các số nhận dạng đã xuất .
  • Kiểm tra hộp trắng: Sử dụng package myfuncđể bạn có quyền truy cập vào các số nhận dạng không được xuất. Tốt cho các bài kiểm tra đơn vị yêu cầu quyền truy cập vào các biến, hàm và phương pháp không được xuất.

So sánh các chiến lược được liệt kê trong câu hỏi

  • Chiến lược 1: Tệp myfunc_test.gosử dụng package myfunc- Trong trường hợp này, mã kiểm tra trong myfunc_test.gosẽ nằm trong cùng một gói với mã đang được kiểm tra myfunc.go, myfunctrong ví dụ này.
  • Chiến lược 2: Tệp myfunc_test.gosử dụng package myfunc_test- Trong trường hợp này, mã kiểm tra trong myfunc_test.go"sẽ được biên dịch thành một gói riêng biệt, sau đó được liên kết và chạy với tệp nhị phân kiểm tra chính." [Nguồn: Dòng 58–59 trong mã nguồn test.go ]
  • Chiến lược 3: Tệp myfunc_test.gosử dụng package myfunc_testnhưng nhập myfuncbằng ký hiệu dấu chấm - Đây là một biến thể của Chiến lược 2, nhưng sử dụng ký hiệu dấu chấm để nhập myfunc.

1
Cần lưu ý rằng việc sử dụng Chiến lược 1 cũng sẽ giữ các tệp _test.goriêng biệt với gói đang được thử nghiệm (hành vi tương tự như Chiến lược 2). Điều này dường như không được ghi lại theo github.com/golang/go/issues/15315
Kevin Deenanauth

Tôi đã thấy gói sử dụng Chiến lược 3 mạnh mẽ, nhưng tôi không thể hiểu điểm chính là gì?
PickBoy

1
Tôi đã tách một gói và thực hiện các thay đổi, và bây giờ tất cả các thử nghiệm của tôi đều đang cố gắng nhập repo gốc thay vì gói đã chia của tôi. Với Chiến lược 3, tôi không phải thay đổi "github.com/original/link" thành "github.com/my/fork", vì nó chỉ là tham chiếu '.' thay thế.
nmarley

1
@KevinDeenanauth Điều này làm tôi ngạc nhiên. Tôi nghĩ rằng tôi đã tìm thấy một cạm bẫy khi tôi chỉ tìm thấy một _test.go_testtên không phải gói chứa một func init()thay đổi một số biến gói toàn cầu để thử nghiệm. Tôi đã sai.
Zyl

1
@nmarley .không giải quyết được vấn đề fork của bạn. Nó không phải là một nhập khẩu tương đối. Nó chỉ nhập các định danh "vào gói hiện tại".
qaisjp

19

Nó phụ thuộc vào phạm vi thử nghiệm của bạn. Các bài kiểm tra cấp cao (tích hợp, chấp nhận, v.v.) có lẽ nên được đặt trong một gói riêng biệt để đảm bảo rằng bạn đang sử dụng gói thông qua API đã xuất.

Nếu bạn có một gói lớn với nhiều phần tử bên trong cần được kiểm tra thì hãy sử dụng cùng một gói cho các thử nghiệm của bạn. Nhưng đó không phải là lời mời để các thử nghiệm của bạn truy cập vào bất kỳ trạng thái riêng tư nào. Điều đó sẽ khiến việc tái cấu trúc trở thành một cơn ác mộng. Khi tôi viết cấu trúc, tôi thường triển khai các giao diện. Đó là các phương thức giao diện mà tôi gọi ra từ các thử nghiệm của mình, không phải tất cả các phương thức / chức năng trợ giúp riêng lẻ.


13

Bạn nên sử dụng chiến lược 1 bất cứ khi nào có thể. Bạn có thể sử dụng foo_testtên gói đặc biệt để tránh các chu kỳ nhập, nhưng đó là chủ yếu ở đó để thư viện chuẩn có thể được kiểm tra với cơ chế tương tự. Ví dụ: stringskhông thể được kiểm tra với chiến lược 1 vì testinggói phụ thuộc vào strings. Như bạn đã nói, với chiến lược 2 hoặc 3, bạn không có quyền truy cập vào các mã nhận dạng riêng của gói, vì vậy tốt hơn là không sử dụng nó trừ khi bạn phải làm như vậy.


10
Làm thế nào không có quyền truy cập vào số nhận dạng riêng tư trong các thử nghiệm không phải là một đức tính tốt?
joong0bs

3
theo các phương pháp kiểm tra tốt, bạn không kiểm tra chi tiết triển khai nội bộ cho một tạo tác mã; làm con trai, là một mã mùi
Gerardo Lima

0

Một lưu ý quan trọng mà tôi muốn bổ sung import .từ Golang CodeReviewComments :

Biểu import .mẫu có thể hữu ích trong các thử nghiệm, do phụ thuộc vòng tròn , không thể được tạo thành một phần của gói đang được thử nghiệm:

package foo_test

import (
    "bar/testutil" // also imports "foo"
    . "foo"
)

Trong trường hợp này, tệp kiểm tra không thể nằm trong gói foo vì nó sử dụng bar/testutil, tệp này nhập foo. Vì vậy, chúng tôi sử dụng 'nhập'. để cho phép tệp giả vờ là một phần của gói foo mặc dù không phải.

Ngoại trừ trường hợp này, không sử dụngimport . trong các chương trình của bạn. Nó làm cho các chương trình khó đọc hơn nhiều vì không rõ liệu một tên như Quux có phải là định danh cấp cao nhất trong gói hiện tại hay trong một gói được nhập hay không.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.