assertThat - hamcrest - проверить, если список отсортирован

хорошо, я думаю, что это будет короткий вопрос. У меня есть ArrayList, который я отсортировал по дате, конечно, я вижу, что он работает, но я также хотел бы написать тест для него.

Я хочу проверить, является ли следующее значение (дата) в моем списке ниже предыдущего. Я могу сделать это с помощью некоторых for s и добавление списка temp, но мне интересно, есть ли более простое решение. Я читал в документации hamrest, что есть что-то вроде contains(содержит hamrest), которые проходят через объект (список, карта и т. д.), Но я все еще не знаю, что делать дальше.

6 ответов


[Первый Вариант]: вы можете написать свой собственный Matcher. Что-то вроде (отказ от ответственности: это всего лишь пример кода, он не тестируется и может быть не идеальным):

@Test
  public void theArrayIsInDescendingOrder() throws Exception
  {
    List<Integer> orderedList = new ArrayList<Integer>();
    orderedList.add(10);
    orderedList.add(5);
    orderedList.add(1);
    assertThat(orderedList, isInDescendingOrdering());
  }

  private Matcher<? super List<Integer>> isInDescendingOrdering()
  {
    return new TypeSafeMatcher<List<Integer>>()
    {
      @Override
      public void describeTo (Description description)
      {
        description.appendText("describe the error has you like more");
      }

      @Override
      protected boolean matchesSafely (List<Integer> item)
      {
        for(int i = 0 ; i < item.size() -1; i++) {
          if(item.get(i) <= item.get(i+1)) return false;
        }
        return true;
      }
    };
  }

этот пример с IntegerS, но вы можете сделать это с Date s легко.

[второй вариант], основываясь на ссылке на contains в вопросе OP: вы можете создать второй список, заказав оригинальный, чем с помощью assertThat(origin, contains(ordered)). Таким образом, возможная ошибка больше точно описано, так как, если элемент не находится в ожидаемом порядке, он будет указан. Например, этот код

@Test
  public void testName() throws Exception
  {
    List<Integer> actual = new ArrayList<Integer>();
    actual.add(1);
    actual.add(5);
    actual.add(3);
    List<Integer> expected = new ArrayList<Integer>(actual);
    Collections.sort(expected);
    assertThat(actual, contains(expected.toArray()));
  }

будет генерировать описание

java.lang.AssertionError: 
Expected: iterable containing [<1>, <3>, <5>]
     but: item 1: was <5>
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
    at org.junit.Assert.assertThat(Assert.java:865)
    at org.junit.Assert.assertThat(Assert.java:832)
    ...

здесь открыть запрос на такой сопоставитель, но, к сожалению, он еще не реализован.

Я бы пошел на что - то гораздо проще-скопируйте список, отсортируйте его и сравните с оригиналом:

@Test
public void testListOrder() {
    ArrayList<SomeObject> original = ...;
    ArrayList<SomeObject> sorted = new ArrayList<SomeObject>(original);
    Collections.sort(sorted);
    Assert.assertEquals ("List is not sorted", sorted, original);
}

EDIT:
@dsncode имеет хороший момент в комментариях-хотя (относительно) элегантный, это решение не разработано с учетом производительности. Если список не слишком велик, он должен быть в порядке, но если список Большой, его сортировка это может дорого стоить. Если список Большой, может быть хорошей идеей перебрать его напрямую и не выполнить тест, если вы столкнулись с элементом, который меньше предыдущего. Например.:

assertTrue(() -> {
    Iterator<SomeClass> iter = list.iterator();

    SomeClass prev = null;
    if (iter.hasNext()) {
        prev = iter.next();
    }

    SomeClass curr = null;
    while (iter.hasNext()) {
        curr = iter.next();
        if (curr.compareTo(prev) < 0) {
            return false;
        }
        prev = curr;
    }

    return true;
});

также можно проверить его с помощью GUAVA:

import com.google.common.collect.Ordering;

...

assertTrue(Ordering.natural().isOrdered(list));

подробнее здесь: как определить, отсортирован ли список на Java?


для небольших коллекций я предлагаю предоставить ожидаемую коллекцию, жестко закодированную в коде. Это модульный тест и не должен содержать никакой логики. После этого можно сравнить две коллекции. (используйте hamcrest чтобы проверить эквивалент)


У меня была аналогичная проблема, я просто проверяю, больше ли следующее значение даты в миллисекундах/меньше, чем предыдущее в этом списке.

/**
 * Test sort by date
 */
@Test
public void findAllMessagesSortByDate() {
    Collection<Message> messages = messageService.getAllMessagesSortedByDate();
    long previousTime = messages.iterator().next().getDate().getTimeInMillis();
    for (Message message : messages) {
        assertTrue(message.getDate.getTimeInMillis() <= previousTime);
        previousTime = message.getMessageFolderTs().getTimeInMillis();
    }
}

вы можете проверить мой ответ в другой теме, но подход остается прежним - вы должны проверить, если элементы в порядке.

Как проверить, содержит ли коллекция элементы в заданном порядке с помощью Hamcrest

этот подход предполагает использование библиотеки "Hamcrest".

надеюсь, что это помогает.