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