2013-10-25 2 views
0

Это скорее вопрос логики junit, чем что-либо еще.Junit: Разделение тестовых примеров

Сценарий У меня ниже:

У меня есть отдельное приложение Java, который потребляет данные из веб-службы и сохраняет данные из этого сервиса на клиенте (где запущено приложение) машины.

Эти данные сохраняются в форме XML и затем считываются другим приложением для визуализации этого содержимого в толстом клиентском интерфейсе.

Поток показан на рисунке ниже:

enter image description here

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

Еще одна часть головоломки - как проверить (единичный тест) то, что было отображено в пользовательском интерфейсе, с XML, который был сохранен на компьютере клиента.

Я понимаю, что каждый юнит должен быть как можно меньше и должен самостоятельно тестировать базовую функциональность.

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

Любая помощь будет оценена по достоинству.

В приведенном выше сценарии, для простоты, я показал автономное приложение и толстый клиент как отдельный, но по существу они могут быть одним приложением.

Толстый клиент, который считывает отображаемые XML-данные, закодирован в javafx.

ответ

3

Вы не указали, каким будет UI? Будет ли это графическое приложение или веб-приложение? Это влияет на общий подход, но для того, чтобы дать некоторые подсказки, я поделюсь своим опытом. Я сделал много приложений с использованием swing, и это будет моя базовая линия.

Итак, тенденция заключается в том, чтобы сделать ваш графический интерфейс максимально тонким и поставить туда логику, которая отвечает только за отображение компонентов. Для этого вы можете использовать хорошо известные шаблоны проектирования, такие как Presentation Model (http://martinfowler.com/eaaDev/PresentationModel.html) или пассивный вид (http://martinfowler.com/eaaDev/PassiveScreen.html)

Затем вы начинаете тестирование своей бизнес-логики. Общие руководящие принципы:

  • Вы не используете внешние ресурсы (файлы, базы данных и т. Д.), Вместо этого вы заменяете их фальшивыми или Mocks, которые предоставляют определенный фиксированный ввод для ваших тестов.
  • Вы тест только поведение класса не поведение зависимостей
  • Try, чтобы избежать сложного ввода
  • Используя упомянутые модели вы можете издеваться своим видом слоя и тестом только ли определенные методы зрения, где называются в synchrronization слое ,

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

@example

У меня нет опыта работы с JavaFX, так что я попытаюсь показать, как я хотел бы сделать это в Swing. В этом примере предполагается, что вы знаете, что такое mocks и для чего они предназначены.

Сначала давайте выясним, что является наиболее важной функциональностью в тонком клиенте. Я бы пошел на что-то подобное. Пользователь открывает файл xml и приложение отображает его в той или иной форме. (Форма не важна, это может быть дерево, это может быть таблица или сетка. Так как это представление мне сейчас все равно)

Основной сценарий: пользователь выбирает файл, приложение открывает этот файл и анализирует его, а затем отображается результат. Давайте назовем этот сценарий «Open Results».

Первый тест:

class OpenResultsShould{ 
    @Test 
    public void loadResults() { 
     Data fake = mock (Data.class); 
     ViewInterface view = mock(ViewInterface.class); // mocking view 
     when(view.getFilename()).thenReturn("file.xml"); // we specify that when getFileName() method of view mock will be called "file.xml" string will be returned. 

     ApplicationModelInterface appModel = mock(ApplicationModelInterface.class); // mocking app model 
     when(appModel.getDataForView()).thenReturn(fake); 

    OpenResultsAction openResults = new OpenResultsAction(view, appModel); 

     openResults.actionPerformed(new ActionEvent()); 

     verify(view).getFileName();   // checks that view.getFileName was called within actionPerdormed() 
     verify(appModel).load("file.xml"); // check that appModel.load() with file.xml as parameter was called within actionPerformed() 
     verify(appModel).getDataForView(); // similar to above 
     verify(view).loadDataFromModel(fake); // finally I check if loadDataFromModel on view was called. 
    } 
} 

Целью данного теста является проверка, если OpenResultsAction будет делать эту работу. Здесь мы не проверяем, что анализируется, и имеет ли gui правильные данные. Мы проверяем, вызывались ли определенные методы для определенных объектов. В этом тесте также указывается контракт между классом действий, представлением и applicationModel. Это делается через интерфейсы. Поэтому вы можете позже предоставить конкретную реализацию, которая будет протестирована на следующем этапе. Тогда я бы предоставил реализацию, которую я пропущу, чтобы сделать этот пример как можно короче.

Так что же дальше. Поскольку gui не собирается тестироваться вообще, я бы пошел на тесты ApplicationModel. В первом тесте мы указали, что applicationModelInterface должен иметь загрузку метода (String filename); И мы будем проверять его конкретную реализацию.

class ApplicationModelShould{ 
    @Test 
    public void loadModelFromFile() { 
     XMLDocument xml = new XMLDocumentFake(); 
     XMLFileLoader xFileLoader = mock(XMLFileLoader.class); 
     when(xFileLoader.load("file.xml").thenReturn(xml); 
     ApplicationModelInterface appModel = new ConcreteApplicationModel(new FileLoaderFake()); 

     appModel.load("plik.xml"); // it should call xFileLoader and then parse returned xml document. 
     doReturn(xml).when(xFileLoader).load("plik.xml"); // verifies if xFileLoader returned xml when appModel.load called it's load method. 
     Data expectedResult = populateExpectedResults(); 
     assertEquals(appModel.getDataForView().equals(expectedResult)); 
    } 
} 

Что такое XMLDocument? Он хранит содержимое xml-файла. Он может быть представлен как вектор файловых строк. Наш AppModelLoader будет анализировать его на объекты. XFileLoader - это еще один слой, который позволяет мне избавиться от операций с файлами в моих модульных тестах. Здесь он издевается, но в реальном приложении его нужно заменить чем-то, что будет читать в XML-файле и возвращать XMLDocument. Данные - это класс, который будет использоваться для хранения анализируемых данных. Если содержание XML является "< Person > < имени > Тома </имя > < возраста/возраст > </Person > затем данные будут выглядеть следующим образом:.

class Data{ 
    private Person person; 
    Data(Person person){ this.person = person; } 
    ... 
}; 

class Person{ 
    private String name; 
    private int age; 
    .... setters, getters and constructors 
} 

И это в основном это, конечно требуется больше тестов, например, если view.getFileName() вернет пустую строку в OpenResultsAction (аннулирование пользователя на JFileChooser), тогда мне нужно проверить, не вызвано ли что-либо еще. Если бы у меня были все тестированные классы, я бы написал GUI часть и объединить его.

Сообщите мне, если это имеет смысл.

+0

Спасибо за отличный ответ [Luke] (http://stackoverflow.com/users/2862100/luke). Я редактировал свой вопрос с информацией о толстом клиенте (javafx). Есть ли способ подделать или издеваться над контентом для приложения javafx? Или, если уж на то пошло, как это можно было бы решить для качающегося приложения? – Aspirant

+1

Я отредактировал свой ответ на примере. Он начинается после @Example – Luke

Смежные вопросы