Mã kiểm tra sao chép và dán: Điều này tệ đến mức nào?


12

Công việc hiện tại của tôi chủ yếu là viết mã kiểm tra GUI cho các ứng dụng khác nhau mà chúng tôi làm việc. Tuy nhiên, tôi thấy rằng tôi có xu hướng sao chép và dán rất nhiều mã trong các bài kiểm tra. Lý do cho điều này là các khu vực tôi đang thử nghiệm có xu hướng tương tự nhau, cần lặp lại nhưng không đủ tương tự để đóng gói mã vào các phương thức hoặc đối tượng. Tôi thấy rằng khi tôi cố gắng sử dụng các lớp học hoặc phương thức rộng rãi hơn, các bài kiểm tra trở nên cồng kềnh hơn để duy trì và đôi khi hoàn toàn khó viết ngay từ đầu.

Thay vào đó, tôi thường sao chép một đoạn lớn mã kiểm tra từ một phần và dán nó vào phần khác, và thực hiện bất kỳ thay đổi nhỏ nào tôi cần. Tôi không sử dụng các cách mã hóa có cấu trúc hơn, chẳng hạn như sử dụng nhiều nguyên tắc hoặc chức năng OO hơn.

Các lập trình viên khác có cảm thấy như vậy khi viết mã kiểm tra không? Rõ ràng tôi muốn tuân theo các nguyên tắc DRY và YAGNI, nhưng tôi thấy rằng mã kiểm tra (mã kiểm tra tự động để kiểm tra GUI dù sao) có thể làm cho các nguyên tắc này khó tuân theo. Hay tôi chỉ cần thực hành mã hóa nhiều hơn và một hệ thống tổng thể tốt hơn để làm mọi thứ?

EDIT: Công cụ tôi đang sử dụng là SilkTest, ngôn ngữ độc quyền có tên 4Test. Đồng thời, các thử nghiệm này chủ yếu dành cho các ứng dụng máy tính để bàn Windows, nhưng tôi cũng đã thử nghiệm các ứng dụng web bằng cách sử dụng thiết lập này.


Bạn đang sử dụng công cụ kiểm tra nào? Có thể khung kiểm tra của bạn không hỗ trợ các loại bài kiểm tra bạn đang viết. Cut-n-paste của hơn 3 dòng nói chung là rất tệ, nhưng nếu bạn có thể thêm rõ ràng giá trị lâu dài hơn bằng cách tự động hóa kiểm tra GUI hơn là thực hiện thủ công mọi lúc, thì bất cứ điều gì bạn đang làm có lẽ rất dễ xảy ra tốt
GlenPeterson

Ngoài ra, ngôn ngữ này là gì? Bạn có thể có một cái gì đó có sẵn mà không xuất hiện trong tâm trí, điều đó sẽ cho phép tái sử dụng (như các hàm hạng nhất). Mặt khác, các trường hợp thử nghiệm được cho là đơn giản, để giữ cho nó ít có khả năng chúng có lỗi hơn ...
Izkata

3
Trong bất cứ điều gì tôi đã viết, mã kiểm tra không được loại trừ khỏi tái cấu trúc ..
Simon Whitehead

Câu trả lời:


23

Sao chép-dán và sau đó chỉnh sửa trường hợp thường ổn.

Các xét nghiệm nên có càng ít phụ thuộc bên ngoài càng tốt, và càng đơn giản càng tốt. Các trường hợp thử nghiệm có xu hướng thay đổi theo thời gian và các trường hợp thử nghiệm gần như giống hệt nhau trước đây có thể đột ngột phân kỳ. Cập nhật một trường hợp thử nghiệm mà không phải lo lắng về việc phá vỡ các trường hợp khác là một điều tốt.

Tất nhiên, mã soạn sẵn giống hệt nhau trong nhiều trường hợp thử nghiệm và phải thay đổi trong buổi hòa nhạc có thể và nên được đưa ra.


1
Đây chủ yếu là cảm giác của tôi. Mã kiểm tra gần giống nhau là ok trong nhiều trường hợp, nhưng mã kiểm tra giống hệt nhau lặp đi lặp lại là tin xấu.
joshin4colours

12

Sự lặp lại là gốc rễ của mọi tội lỗi

Đúng vậy! Sự lặp lại là gốc rễ của mọi tội lỗi . Có lẽ đó là câu nói của Knuth trong cuốn sách Tối ưu hóa sớm của anh ấy là gốc rễ của tất cả những điều xấu xa, nhưng tôi nghĩ đó là sự lặp lại.

Bất cứ khi nào bạn nhìn vào một chương trình hoặc bạn đang viết một chương trình và bạn phát hiện ra một loại lặp lại: Loại bỏ nó! Giết nó ngay lập tức, bất cứ điều gì nhưng thoát khỏi nó !

Mỗi lần tôi giới thiệu một số loại lặp lại và phải sửa một lỗi trong đó, tôi đã quên sửa bản sao ... (Donald Knuth) Vì vậy, bất cứ khi nào có sự lặp lại, hãy xóa nó một cách tốt nhất có thể, đừng hack !

Hãy nghĩ về một thiết kế tinh gọn (như, đóng gói các khối mã lặp lại của bạn trong các lớp của trình trợ giúp) và viết một số thử nghiệm trước khi thay đổi một cái gì đó (chỉ để chắc chắn rằng bạn đã không phá vỡ thứ gì đó). Điều này đúng với bất kỳ đoạn mã nào được viết và mã kiểm tra cũng không ngoại lệ.

Đây là một bài đọc hay từ Mã kinh dị truyền cảm hứng cho tôi - Đề xuất khiêm tốn nhất cho trường hợp tái sử dụng và sao chép mã trường .


"Mỗi lần tôi giới thiệu một số loại lặp lại và phải sửa một lỗi trong đó, tôi đã quên sửa bản sao chính xác". Ngoài ra, nếu bạn c & p và bạn quên điều chỉnh văn bản đã sao chép vào bối cảnh hiện tại thì điều này sẽ gây tổn hại rất nhiều. Mã kiểm tra bị lỗi không giống như tình huống tối ưu, bây giờ phải không?
marktani

yeap, tôi đã lấy các trạm từ Knuth :)
Yusubov

9
Bạn lặp lại chính mình: Bạn lặp lại chính mình bằng cách nói "Sự lặp lại là gốc rễ của mọi tội lỗi" trong tiêu đề và câu giới thiệu của bạn.
Thomas Eding

Yeap, tôi đã cố tình làm điều đó để nhấn mạnh tầm quan trọng và bạn được hoan nghênh chỉnh sửa phần đó :)
Yusubov

1
Thomas Eding, bạn cũng lặp lại chính mình. Bạn cũng lặp lại chính mình =)
marktani

7

Nó vẫn còn khá tệ để cắt và dán. Có một vài vấn đề.

Các bài kiểm tra của bạn có thể rất dễ vỡ, bởi vì bạn dễ bị tổn thương trước một điều gì đó đòi hỏi phải thay đổi tất cả các mã sao chép và dán đó. Bạn sẽ phải viết lại tất cả các bài kiểm tra?

Nếu bạn không thể gói logic vào các phương thức của trình trợ giúp bên ngoài các bài kiểm tra của mình, bạn không thể tự viết các bài kiểm tra cho các phương thức của trình trợ giúp đó. Viết các bài kiểm tra về các phương pháp kiểm tra thường rất khó để tạo ra giá trị, vì bạn phải phá mã để kiểm tra. Nhưng bạn có thể đơn vị thử nghiệm phương pháp trợ giúp.

Nó cũng có thể làm cho các bài kiểm tra ít đọc hơn. Một khối lớn mã được sao chép có thể khó đọc hơn phương thức gọi tới trình trợ giúp với tên mô tả.

Tất cả mọi thứ tôi đã liệt kê là một cái gì đó có thể là một vấn đề. Nếu bạn thấy không ai trong số họ thực sự một vấn đề thì tất nhiên là ổn rồi.


> một cuộc gọi đến phương thức trợ giúp với một tên mô tả. Đây không phải là vấn đề với việc các bài kiểm tra đơn vị của bạn hiện đang trở thành các chương trình - điều mà chúng tôi muốn tránh. Điều gì xảy ra nếu một số thử nghiệm không thành công - đó có phải là mã bị hỏng hoặc người trợ giúp thử nghiệm không?
dwjohnston

4

Tôi đã từng đồng ý với bạn. Nhưng sau đó, theo thời gian, tôi thấy rằng mọi thay đổi tôi đã thực hiện (đặc biệt là thay đổi DI trong các bài kiểm tra đơn vị) đòi hỏi nhiều bài kiểm tra để thay đổi và điều đó thật cồng kềnh. Bây giờ tôi đăng ký vào trường DRY, ngay cả khi viết bài kiểm tra.

Để kiểm tra GUI, bạn có thể muốn xem mẫu PageObject để giảm mã lặp lại.


2

Tôi khuyên bạn nên chọn mẫu XUnit. Tôi đã từng có cùng một vấn đề cho đến khi tôi bắt đầu tận dụng cuốn sách đó. Mẫu Object Object nghe có vẻ hữu ích nhất cho kịch bản của bạn.

Giống như một người khác được đề cập, việc đóng gói mã thiết lập này có thể rất khó khăn, nhưng phải thay đổi nó ở tất cả những nơi bạn sao chép và dán thậm chí còn hơn thế.


+1 cho Object Mother patternmã khởi tạo chung.
k3b

2

Mọi người nên cố gắng và hạn chế sự phục hồi khi họ có thể - có. Nhưng mức chi trả phụ thuộc vào tình hình. Điều này có thể quay trở lại cuộc tranh luận 'thực tiễn tốt nhất'. Nhưng câu hỏi là điều gì là tốt nhất cho bạn trong tình huống này. Có ngoại lệ cho mọi quy tắc.

Một vài điều tôi sẽ hỏi là: 1) Khả năng chức năng này đang được thử nghiệm trong UAT sẽ thay đổi như thế nào? Nếu không chắc nó sẽ thay đổi, thì ít có khả năng bạn sẽ phải cập nhật từng bộ mã của mình. 2) Nếu có thay đổi trong UAT, nó sẽ luôn tác động đến từng bộ mã được sao chép hay chỉ có thể tác động đến một hoặc hai bộ? Nếu nó có thể bị cô lập và chỉ yêu cầu thay đổi thành một bộ, thì có thể giúp tách rời mọi thứ. 3) Phương pháp ban đầu sẽ phức tạp đến mức nào nếu bạn thử và để nó xử lý tất cả các tình huống? Bạn có đang thêm rất nhiều if / other / loop không? Nếu bạn bắt đầu làm quá mức tất cả các nhánh, bạn có thể kết thúc với mã khó hiểu. Sẽ dễ dàng hơn để thực hiện cập nhật trong mỗi văn bản được sao chép hơn là xem lại tất cả logic phân nhánh?

Nếu bạn bị kẹt sao chép / dán / thay đổi, tôi nghĩ bạn sẽ muốn thêm nhận xét, chẳng hạn như 'Điều này được sao chép trong phương thức xyz'. Bằng cách đó, bạn sẽ được nhắc nhở cập nhật tất cả các phiên bản đã dán của mã. Hoặc (đến từ một người dùng SilkTest khác) bạn có thể thêm một tệp inc riêng biệt chỉ tập trung vào mã lặp lại này. Bằng cách đó, bạn có tất cả các biến thể ở một nơi và có thể dễ dàng thấy các phương thức khác nhau sẽ yêu cầu cập nhật.


0

Một thủ tục lớn

Một suy nghĩ: Có vẻ như bạn đang cố gắng tránh mã cut-n-paste bằng cách thực hiện các phương thức như:

testScreen(title, fieldList, linkList, param1, param2, param3,...) {
    test that the layout at the top of the screen is correct
    test if PageTitle == title?
    for each field in fieldList:
        check that it appears in order on the screen
    for each field in linkList:
        check that it appears in order on the screen
    test if param1 is whatever...
    test if param2 is whatever...
    etc.
    test that the bottom of the screen is correct
}

Nhiều thủ tục nhỏ (bộ công cụ)

Bạn cũng đã xem xét cách tiếp cận ngược lại? Thay vì chuyển một triệu tham số cho một thủ tục testScreen () lớn, có thể tạo khung công cụ hoặc bộ công cụ của riêng bạn về các thủ tục trợ giúp nhỏ mà bạn rút ra khi bạn cần chúng. Giống:

testScreenTop()
verifyLinks(list)
testScreenBottom()

Bạn vẫn cắt và dán các quy trình này vào mọi màn hình, nhưng bạn đang cắt và dán các đoạn mã nhỏ hơn và khắc ra các đoạn phổ biến không bị cắt và dán (nội dung của từng thủ tục nhỏ).

Cắt và dán

Lần duy nhất mã bị cắt và dán không cắn tôi là khi mã bị vứt đi trước khi tôi phải thay đổi nó. Mối quan tâm lớn nhất của tôi với các bài kiểm tra UI là chúng nhanh chóng trở nên lỗi thời như thế nào. Nếu bạn thấy bạn vứt tất cả mã của mình đi trước khi bạn thay đổi nó, thì có lẽ bạn đã tìm thấy một nơi thích hợp để cắt và dán là OK! Ngoài ra, nó không quá tệ khi không có mã xuôi dòng từ mã cắt và dán (ví dụ: trong giao diện người dùng của ứng dụng). Nếu bạn đang dán hơn 3 dòng, tôi thực sự muốn làm gì đó với nó. Ít nhất là thực hiện các bước để giảm thiểu nó!

Kiểm tra giao diện người dùng tự động

Heck, nếu bạn có thể chứng minh năng suất cao hơn với kiểm tra giao diện người dùng tự động so với kiểm tra thủ công bằng bất kỳ kỹ thuật nào (chi phí viết / duy trì kiểm tra tự động thấp hơn kiểm tra thủ công mỗi lần, nhưng chất lượng là như nhau) Tôi nghĩ bạn nên viết một bài báo. Tôi sẽ đọc nó! Bây giờ tôi có thể thấy tiêu đề, "Cắt và dán mã Win Win để kiểm tra giao diện người dùng!"


0

Nó thực sự không tệ. Trong thực tế, nếu bạn thấy các mẫu mã nhất định đang được sử dụng rất thường xuyên và các thay đổi rất thường xuyên (chẳng hạn như một vài chuỗi hoặc giá trị tham số), bạn thậm chí có thể viết một trình tạo mã tạo mã kiểm tra lặp lại dựa trên một số nhỏ (- ish?) danh sách đầu vào của các giá trị thay đổi. Tôi đã thực hiện việc này (mã kiểm tra được tạo) nhiều lần, bằng cách sử dụng các tệp bó, tập lệnh SQLPlus, thậm chí là macro Excel (nghe có vẻ xấu, nhưng các biến cho các tập lệnh kiểm tra khác nhau đã có trong một bảng tính) và nó có thể là một trình tiết kiệm thời gian tuyệt vời . Vấn đề là nếu bất cứ điều gì thay đổi trong cấu trúc tổng thể của mã trường hợp kiểm tra lặp đi lặp lại, bạn có thể chỉ cần tạo lại bất cứ thứ gì bạn cần.


0

Điều này giống như hầu hết các câu trả lời khác nhưng theo cách mà một người quản lý không có kỹ thuật có thể hiểu.

Hãy tưởng tượng kịch bản lỗi sau:

  • Ai đó thực hiện thay đổi cho cơ sở dữ liệu trong đó nhiều bài kiểm tra của bạn phụ thuộc vào.
  • Hậu quả: đột nhiên 117 trong số 2933 bài kiểm tra tự động của bạn không thành công.

Bạn sẽ làm gì?

  • (1) sửa 117 bài kiểm tra?
  • (2) xóa 117 bài kiểm tra và thực hiện lại chúng thông qua bản sao và dán mới. điều này có thể dễ dàng hơn (1)
  • (3) cấu trúc lại các bài kiểm tra để trích xuất mã chung để trong tương lai bạn chỉ phải điều chỉnh một phương thức (hoặc một vài) để sửa các bài kiểm tra (xem câu trả lời của @pdr hoặc @Michael Brown)
  • (4) xóa 117 bài kiểm tra mà không thực hiện lại các bài kiểm tra

Từ kinh nghiệm của tôi:

Khi giới thiệu quản lý kiểm tra tự động như "sao chép & dán kiểm tra": bạn nhận được nhiều bài kiểm tra trong một thời gian ngắn.

Sau một số "kịch bản lỗi" quản lý thích (4) vì sửa lỗi "sao chép và dán kiểm tra" rất tốn kém.

Làm điều đó ngay từ đầu (3) sẽ không nhanh như vậy nhưng làm tăng khả năng các bài kiểm tra sẽ sống sót

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.