2013-07-16 39 views
5

Tôi có một nguồn dữ liệu mà từ đó tôi có thể yêu cầu một danh sách những người sống ở một quốc gia (bất kỳ) và phương thức truy xuất những người từ nguồn dữ liệu đó và sắp xếp chúng theo tên của họ theo thứ tự bảng chữ cái. Làm thế nào tôi nên viết bài kiểm tra đơn vị của mình để đảm bảo rằng phần sắp xếp của phương pháp của tôi hoạt động chính xác?Làm cách nào để viết một bài kiểm tra đơn vị để xác minh rằng một hàm sắp xếp kết quả của nó?

Đây là những gì SUT của tôi trông giống như:

class PeopleStuff { 

    public IData data; 

    public List<Person> getSortedPeopleForCountry(String countryName) { 
     List<Person> people = data.getPeopleForCountry(countryName); 

     Comparator nameComparator = new PersonNameComparator(); 
     Collections.sort(people, nameComparator); 

     return people; 
    } 

} 

Và đây là những gì thử nghiệm đơn vị của tôi trông giống như:

@Test public void testGetPeopleSortsByPeopleName() { 
    String COUNTRY = "Whatistan"; 

    // set up test (the 3 lines below are actually in a @Before setup method) 
    PeopleStuff peopleStuff = new PeopleStuff(); 
    IData mockData = createNiceMock(IData.class); 
    peopleStuff.data = mockData; 

    // set up data 
    List<PersonName> mockPeopleList = new ArrayList<PersonName>(); 
    mockPeopleList.add(new Person(COUNTRY, "A")); 
    mockPeopleList.add(new Person(COUNTRY, "D")); 
    mockPeopleList.add(new Person(COUNTRY, "B")); 
    mockPeopleList.add(new Person(COUNTRY, "C")); 

    when(mockData.getPeopleForCountry(COUNTRY)).thenReturn(mockPeopleList); 

    // exercise 
    List<String> result = peopleStuff.getSortedPeopleForCountry(COUNTRY); 

    // assert 
    assertEquals("A", result.get(0).name); 
    assertEquals("B", result.get(1).name); 
    assertEquals("C", result.get(2).name); 
    assertEquals("D", result.get(3).name); 
} 

Những gì tôi cần biết là nếu cách này tôi đang stubbing dữ liệu , chạy thử nghiệm và đưa ra các xác nhận là chính xác hoặc nếu có cách tốt hơn để thực hiện việc này.

Ứng dụng của tôi có nhiều phương pháp để kiểm tra và rất nhiều thuật toán sắp xếp tùy chỉnh; Tôi đã thực hiện tất cả các bài kiểm tra để sử dụng một số 4 giá trị mà tôi đã khai như thế, in a "random" order mà tôi chọn khi tôi viết bài kiểm tra.


Tôi có nên kiểm tra các bộ so sánh được gọi không? Điều đó dường như không đúng với tôi, bởi vì tôi không biết liệu họ có được gọi đúng dữ liệu hay đúng thời điểm trong thuật toán bên trong getSortedPeopleForCountry() hay không. Tôi muốn phát hiện những tình huống như thế này:

public List<Person> getSortedPeopleForCountry(String countryName) { 
    List<Person> people = data.getPeopleForCountry(countryName); 

    Comparator nameComparator = new PersonNameComparator(); 
    List<Person> sortedPeople = new ArrayList<Person>(people) 
    Collections.sort(sortedPeople, nameComparator); 

    return people; // oops! 
} 

Tôi có nên để nó như này và thêm bộ so sánh mô hình mà sử dụng bộ so sánh thật nhưng cũng xác nhận rằng họ đang được gọi là?

Tôi có làm đúng không?

+0

Tôi sẽ sắp xếp danh sách và sau đó bắt đầu so sánh các phần tử theo cặp để đảm bảo phần tử * current * có cùng hoặc một quốc gia * lớn hơn * so với trước đó. –

+0

@LuiggiMendoza Tôi đã làm điều đó, nhưng tôi đã đổi ý. Điều đó đã thêm một sự phụ thuộc vào 'PersonNameComparator' bên trong bài kiểm tra. Và nó lấy một vòng lặp 'for' của 3 dòng, có nghĩa là một thuật toán bổ sung trong bài kiểm tra mà người đọc sẽ phải hiểu để hiểu bài kiểm tra. –

+0

Bạn làm cho nó trông giống như 3 dòng mã là khá khó hiểu ... Trong thực tế, vì tôi không làm việc với easymock, tất cả các mã trên cho tôi là cách khó hiểu hơn một vòng lặp 'for' đơn giản với một 'if'. –

Trả lời

2

Tôi nghĩ thử nghiệm hiện tại của bạn rất tốt - các thử nghiệm là thực tế, thực hiện tất cả mã, và bạn đang loại bỏ nguồn dữ liệu & bằng cách sử dụng tiêm phụ thuộc để cung cấp nguồn dữ liệu giả. Có rất nhiều thực hành tốt nhất đang diễn ra trong bài kiểm tra này.

Trên vấn đề liệu bạn nên xem xét để thử các bộ so sánh (và do đó làm cho các thử nghiệm trên testGetPeopleSortsByPeopleName một thử nghiệm đơn vị tinh khiết), bạn chắc chắn sẽ nhận được hai ý kiến ​​khác nhau ở đây:

  • Một purist sẽ cho rằng thử nghiệm của bạn về mặt kỹ thuật là một bài kiểm tra tích hợp, và để có các bài kiểm tra đơn vị thích hợp, bạn cần phải điều chỉnh bài kiểm tra của mình để sử dụng bộ so sánh giả, và sau đó kiểm tra bộ so sánh một cách riêng biệt.
  • Một nhà thực dụng sẽ cho rằng thử nghiệm của bạn đã có chất lượng cao và không quan trọng là nó không phải là một thử nghiệm đơn vị theo nghĩa hẹp nhất. Hơn nữa, để chia thành hai bài kiểm tra đơn vị riêng biệt có thể làm cho bài kiểm tra ít có thể đọc được - mà tôi tưởng tượng sẽ là trường hợp với bài kiểm tra ở trên nếu bạn liên quan đến các trình so sánh giả.

Ý kiến ​​cá nhân của tôi là bạn nên thực hiện bài kiểm tra chất lượng cao, có thể đọc được tất cả mã và xác nhận hiệu quả các yêu cầu của bạn quan trọng hơn rất nhiều kiểm tra đơn vị.

Cách duy nhất để kiểm tra cần cải thiện là độ dài của phương pháp thử - Tôi nghĩ rằng một phương pháp trích xuất ít có thể giúp cải thiện khả năng đọc và làm cho phương pháp thử nghiệm mang tính biểu cảm hơn. Tôi sẽ nhắm tới một cái gì đó như thế này:

@Test public void testGetPeopleSortsByPeopleName() { 

    peopleStuff.data = buildMockDataSource(COUNTRY, "A", "D", "B", "C") 

    List<String> result = peopleStuff.getSortedPeopleForCountry(COUNTRY); 

    assertPersonList(result, "A", "B", "C", "D") 
} 

private IData buildMockDataSource(String country, String ... names) { 
    ... 
} 

private void assertPersonList(List<Person> people, String ... names) { 
    ... 
} 
+0

Được rồi, vì vậy tôi đã đi với điều này và kết thúc với một tấn phương pháp thế hệ sơ khai và phương pháp xác nhận danh sách nhưng điều đó hóa ra tốt bởi vì tôi chỉ cần đặt tất cả chúng trong một tệp trợ giúp thử nghiệm. Các bài kiểm tra trông rất gọn gàng và dễ bảo trì. Cảm ơn. –

1

Phân tách logic phân loại khỏi trả về danh sách. Vì vậy, tôi muốn có getPeopleForCountry (String countryName) chỉ trả về một danh sách trong khi một danh sách được sắp xếp sẽ được trả về từ getSortedPeopleForCountry (List). Bằng cách đó bạn có thể kiểm tra cách nó hoạt động trước và sau khi phân loại. Ngoài ra, bạn có thể muốn ghi đè phương thức Equals() để so sánh tên nếu đó là những gì bạn muốn đi cùng, nhưng sau đó bạn muốn so sánh với một số thuộc tính khác. Đó là cuộc gọi của bạn.

+0

Điều này rất mơ hồ và nó hoàn toàn bỏ qua rằng tôi đã viết rằng tôi có các bộ so sánh tùy chỉnh cho các đối tượng Person. Ngoài ra, đoạn mã này chỉ là một phiên bản ngu ngốc của những gì tôi có trong quá trình phát triển. Câu hỏi đặt ra là làm thế nào để kiểm tra rằng một hàm _looks like_ ví dụ tôi đã viết là phân loại dữ liệu đã cho. –

+0

Làm thế nào để nó bỏ qua bộ so sánh bạn đã viết? Bộ so sánh của bạn sẽ được sử dụng bên trong getSortedPeopleForCountry (Danh sách T) ... từ câu trả lời của tôi. Dù sao, đó là tôi lấy mã của bạn. Nếu bạn có một phương thức thử nghiệm như testGetPeopleForCountryWhenNotSorting(), bạn có thể kiểm tra phương thức phân loại không khác sẽ không kiểm tra. – Mukus

0
ObjectA[] arr = objectAList.toArray(new ObjectA[objectAList.size()]); 
for (int i = 0; i < objectAList.size() - 1; i++) { 
     int j = i + 1; 
     assertTrue(arr[i].getDate().compareTo(arr[j].getDate()) >= 0); 
} 

Mã này đại diện cho một ví dụ nơi ArrayList contaning ObjectA đối tượng được sắp xếp theo ngày trường trong thứ tự giảm dần. Chúng tôi đang kiểm tra xem thành viên của danh sách có ngày nhỏ hơn hoặc bằng nhau từ người tiền nhiệm của anh ấy hay không.