2013-03-01 39 views
9

Tôi có một lớp thử nghiệm được kiểm tra với nhiều kiểm tra đơn vị thường kiểm soát việc tạo các email tùy chỉnh. Ngay bây giờ lớp học có rất nhiều bài kiểm tra mà phụ thuộc vào các yếu tố (s) được sử dụng trong lớp parametrized, dòng chảy của các bài kiểm tra là như nhau cho mỗi bài kiểm tra. Các ví dụ về một bài kiểm tra:Nếu các câu lệnh trong các thử nghiệm

@Test 
public void testRecipientsCount() { 
    assertEquals(3, recipientsCount); 
} 

tôi phải bổ sung thêm funcionality đến lớp email của tôi mà bổ sung thêm một số email nội bộ để danh sách người nhận, và điều đó chỉ xảy ra đối với một số trường hợp và điều đó dẫn đến vấn đề của tôi .

Cho phép nói rằng tôi muốn xác nhận số lượng thư được tạo. Đối với các thử nghiệm cũ nó là như nhau cho mỗi trường hợp, nhưng bây giờ nó khác nhau tùy thuộc vào trường hợp. Cách trực quan nhất đối với tôi là để thêm nếu phát biểu:

@Test 
public void testRecipientsCount(){ 
    if(something) { 
     assertEquals(3, recipientsCount); 
    } 
    else { 
     assertEquals(4, recipientsCount); 
    } 
} 
... 

nhưng kinh nghiệm hơn đồng nghiệp của tôi nói rằng chúng ta nên tránh ifs trong lớp học thử nghiệm (và tôi kinda đồng ý về điều đó). Tôi nghĩ rằng thử nghiệm chia tách trên hai bài kiểm tra có thể làm việc, nhưng điều đó sẽ dẫn đến mã dự phòng trong cả hai lớp (tôi vẫn phải kiểm tra xem các thư không phải là vĩnh cửu đã được tạo, kích thước, nội dung, v.v.) hay không vài dòng được thêm vào cho một trong số chúng.

Câu hỏi của tôi là: làm cách nào để làm điều này vì vậy tôi không sử dụng nếu hoặc tải mã dự phòng (không sử dụng lớp được tham số sẽ tạo ra nhiều mã dự phòng hơn)?

+0

'thêm một số phụ email nội bộ vào danh sách người nhận'. Danh sách các địa chỉ nội bộ đó có được đưa vào lớp không? Nếu vậy, bạn chỉ cần xóa danh sách đó cho hầu hết các bài kiểm tra và có một hoặc hai bài kiểm tra 'testInternalMail' DO điền danh sách đó –

+0

Tôi không nghĩ rằng điều này là có thể với lớp kiểm tra Parametrized. Các trường hợp thử nghiệm được thêm vào mà bạn đề xuất sẽ chạy cho mọi bộ đối số và các xác nhận sẽ khác nhau đối với một số đối số. Giải pháp của bạn sẽ hoạt động mà không có lớp Parametrized, nhưng tôi muốn tránh điều đó. – Raidmaster

+0

Bạn có thể thay đổi mã đã đăng của mình thành lớp kiểm tra hoàn chỉnh hơn (nhưng vẫn nhỏ và giả), vì vậy chúng tôi có thể hiểu cách bạn thiết lập thông số của mình? –

Trả lời

3

Theo tôi, Junit nên được đọc như một giao thức. Điều đó có nghĩa là bạn có thể viết mã dự phòng để làm cho trường hợp thử nghiệm dễ đọc hơn. Viết một testcase cho mỗi câu lệnh if có thể trong logic nghiệp vụ của bạn cũng như các trường hợp âm. Đó là cách duy nhất để có được phạm vi kiểm tra 100%. tôi sử dụng cấu trúc:

- testdata preparation 
- executing logic 
- check results 
- clear data 

Bên cạnh đó bạn nên viết phức tạp khẳng định của các đối tượng lớn trong lớp trừu tượng riêng:

abstract class YourBusinessObjectAssert{ 
    public static void assertYourBussinessObjectIsValid(YourBusinessObject pYourBusinessObject,  Collection<YourBusinessObject> pAllYourBusinessObject) { 
for (YourBusinessObject lYourBusinessObject : pAllYourBusinessObject) { 
    if (lYourBusinessObject.isTechnicalEqual(pYourBusinessObject)) { 
    return; 
    } 
} 
assertFalse("Could not find requested YourBusinessObject in List<YourBusinessObject>!", true); 
} 
} 

nó sẽ làm giảm sự phức tạp của mã của bạn và bạn đang làm cho nó có sẵn cho các nhà phát triển khác.

0

Một thử nghiệm đơn vị, theo ý kiến ​​của tôi, chỉ kiểm tra một điều nếu có thể. Như vậy tôi muốn nói rằng nếu bạn cần một câu lệnh if thì bạn có thể cần nhiều hơn một bài kiểm tra đơn vị - một cho mỗi khối trong mã if/else.

Nếu có thể tôi muốn nói một bài kiểm tra nên đọc như một câu chuyện - bố trí ưa thích của tôi (và nó không ý tưởng của tôi :-) - nó khá sử dụng rộng rãi) là:

- given: do setup etc 
- when: the place you actually execute/call the thing under test 
- expect: verify the result 

Một ưu điểm khác của một đơn vị kiểm tra thử nghiệm chỉ có một điều là khi một thất bại xảy ra rõ ràng của nó nguyên nhân là gì - nếu bạn có một thử nghiệm dài với nhiều kết quả có thể nó trở nên khó khăn hơn nhiều lý do tại sao một thử nghiệm đã thất bại.

0

Tại sao không có phương pháp riêng để kiểm tra những điểm chung cho mỗi phương pháp? Một cái gì đó tương tự (nhưng có lẽ với một số thông số đầu vào cho phương pháp testCommonStuff()):

@Test 
public void testRecipientsCountA(){ 
    testCommonStuff(); 
    // Assert stuff for test A 
} 

@Test 
public void testRecipientsCountB(){ 
    testCommonStuff(); 
    // Assert stuff for test B 
} 

private void testCommonStuff() { 
    // Assert common stuff 
} 

Bằng cách này bạn không nhận được mã dư thừa và bạn có thể chia bài kiểm tra của bạn vào các bài kiểm tra nhỏ hơn. Ngoài ra bạn làm cho các bài kiểm tra của bạn ít dễ bị lỗi NẾU họ thực sự nên kiểm tra những điều tương tự.Bạn vẫn sẽ biết thử nghiệm nào không thành công, do đó truy xuất nguồn gốc sẽ không có vấn đề gì.

+0

Tôi sử dụng lớp Parametrized và nó sẽ chạy cả hai trường hợp thử nghiệm của bạn cho mỗi bộ đối số. Cách đúng là chỉ chạy một, tùy thuộc vào đối số thực tế. – Raidmaster

+0

@ Badman6 Tôi không hoàn toàn có được nó. Bạn nói "nhưng điều đó sẽ dẫn đến mã dự phòng trong cả hai lớp (tôi vẫn phải kiểm tra xem các thư không phải iternal đã được tạo, kích thước, nội dung, v.v.) của chúng" hay chưa. Điều đó không có nghĩa là bạn có mã reduntant trong một hoặc nhiều phương pháp thử nghiệm? Nếu vậy, bạn có thể có nó trong một phương thức riêng tư như trên và gọi nó từ mỗi phương thức sẽ chạy nó. – Magnilex

+0

Không phải vậy. Số người nhận phụ thuộc vào một tham số được chỉ định trong một nhà cung cấp đối số cho lớp tham số. Nếu tôi muốn giữ mã dự phòng lớp Parametrized sẽ là kết quả của việc tách các bài kiểm tra của tôi thành 2 lớp (một cho các trường hợp, một không có người nhận nội bộ). Đối với các bài kiểm tra các lớp học chia sẻ mã không thực sự là một lựa chọn. Bạn giải pháp là ok, chỉ cần không cho Parametrized lớp – Raidmaster

0

Tôi không chắc chắn nếu nó có thể làm sạch những gì bạn đang sau trong một thử nghiệm parametrized. Nếu bạn cần hành vi trường hợp thử nghiệm khác nhau dựa trên tham số nào cho một số tính năng, bạn có thể chỉ nên thử nghiệm các tính năng đó một cách riêng biệt - trong các lớp thử nghiệm khác nhau không được tham số.

Nếu bạn thực sự muốn giữ lại tất cả mọi thứ trong lớp học thử nghiệm parametrized, tôi sẽ nghiêng để thực hiện một chức năng helper để kiểm tra ví dụ của bạn ít nhất là đọc như một sự khẳng định đơn giản:

@Test 
public void testRecipientsCount(){ 
    assertEquals(expectedCount(something), recipientsCount) 
} 

private int expectedCount(boolean which) { 
    if (something){ 
     return 3; 
    } 
    else { 
     return 4; 
    } 
} 
Các vấn đề liên quan