
Лаб. 3 ТПО
.docxЛабораторная работа №3
Тестирование пользовательского интерфейса. CodedUi тесты
Цель работы: Научиться формировать требования к пользовательскому интерфейсу и проводить тестирование графического интерфейса
Задание
CalculatorViewClass
package org.example.demo; import javafx.scene.control.Alert; import javafx.scene.image.Image; import javafx.scene.image.ImageView; public class CalculatorViewClass implements CalculatorView { private String firstArgumentAsString; private String secondArgumentAsString; public CalculatorViewClass(String firstArgumentAsString, String secondArgumentAsString) { this.firstArgumentAsString = firstArgumentAsString; this.secondArgumentAsString = secondArgumentAsString; } @Override public void printResult(double result){ System.out.println("Результат вычисления: " + result); } @Override public void displayError(String message){ //System.out.println("Полученная ошибка: " + message); Alert alert = new Alert(Alert.AlertType.ERROR); alert.setTitle("Ошибка"); alert.setHeaderText(null); alert.setContentText(message); // Создание ImageView для изображения Image image = new Image("file:C:/Users/user/Desktop/МИЭТ/3.1.МИЭТ (3 курс 1 семестр)/Тестирование программного обеспечения/Мои работы/demo/pic.jpg"); ImageView imageView = new ImageView(image); imageView.setFitWidth(700); // Установка ширины изображения imageView.setFitHeight(700); // Установка высоты изображения imageView.setPreserveRatio(true); // Сохранение пропорций изображения // Добавление ImageView в диалоговое окно alert.setGraphic(imageView); alert.showAndWait(); } @Override public String getFirstArgumentAsString(){ return firstArgumentAsString; } @Override public String getSecondArgumentAsString(){ return secondArgumentAsString; } }
Controller
package org.example.demo; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.Alert; import javafx.scene.control.Alert.AlertType; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.AnchorPane; import javafx.stage.Stage; public class Controller { @FXML Label output; double num1 = 0.0; double num2 = 0.0; private AnchorPane anchorPane; private boolean start = true; String operatorVal = ""; String operatorValTest = ""; CalculatorClass cc = new CalculatorClass(); CalculatorViewClass cv = new CalculatorViewClass("", ""); CalculatorPresenterClass cp = new CalculatorPresenterClass(); @FXML void num(ActionEvent event) { String val = ((Button) event.getSource()).getText(); // Проверка на ввод точки if (val.equals(".")) { // Если поле пустое, добавить "0." if (output.getText().isEmpty()) { output.setText("0."); } else if (!output.getText().contains(".")) { // Если в текущем тексте нет точки, добавить её output.setText(output.getText() + val); } return; } // Если текущее значение равно "0", заменить его на новое значение if (output.getText().equals("0")) { output.setText(val); } else { // Добавление значения к текущему тексту output.setText(output.getText() + val); } } @FXML void operator(ActionEvent event) { String val = ((Button) event.getSource()).getText(); String currentText = output.getText(); if (currentText.isEmpty() || currentText.equals(".")) { return; } if (!"=".equals(val)) { if (!operatorVal.isEmpty()) return; operatorVal = val; num1 = Double.parseDouble(output.getText()); output.setText(""); } else { if (operatorVal.isEmpty()) return; num2 = Double.parseDouble(output.getText()); double result = 0.0; try { switch (operatorVal) { case "+": result = cc.sum(num1, num2); cp.onPlusClicked(); break; case "-": result = cc.subtract(num1, num2); cp.onMinusClicked(); break; case "*": result = cc.multiply(num1, num2); cp.onMultiplyClicked(); break; case "/": result = cc.divide(num1, num2); cp.onDivideClicked(); break; } output.setText(String.valueOf(result)); cv.printResult(result); } catch (ArithmeticException e) { cv.displayError("Полученная ошибка: " + e.getMessage()); //displayError(cv.displayError(e.getMessage())); //displayError(e.getMessage()); output.setText(""); } operatorVal = ""; start = true; } } void operatorAlternate(ActionEvent event) { //String val = ((Button) event.getSource()).getText(); //String currentText = output.getText(); /* if (currentText.isEmpty() || currentText.equals(".")) { return; } */ if (!"=".equals(operatorValTest)) { //if (!operatorVal.isEmpty()) return; //operatorVal = val; //num1 = Double.parseDouble(output.getText()); //output.setText(""); } else { //if (operatorValTest.isEmpty()) return; //num2 = Double.parseDouble(output.getText()); double result = 0.0; try { switch (operatorVal) { case "+": result = cc.sum(num1, num2); cp.onPlusClicked(); break; case "-": result = cc.subtract(num1, num2); cp.onMinusClicked(); break; case "*": result = cc.multiply(num1, num2); cp.onMultiplyClicked(); break; case "/": result = cc.divide(num1, num2); cp.onDivideClicked(); break; } //output.setText(String.valueOf(result)); cv.printResult(result); } catch (ArithmeticException e) { cv.displayError("Полученная ошибка: " + e.getMessage()); //displayError(cv.displayError(e.getMessage())); //displayError(e.getMessage()); //output.setText(""); } //operatorVal = ""; //start = true; } } @FXML private void clear(ActionEvent event){ output.setText(""); num1 = 0.0; num2 = 0.0; operatorVal = ""; start = true; } @FXML private void delete(ActionEvent event) { String currentText = output.getText(); if (!currentText.isEmpty()) { output.setText(currentText.substring(0, currentText.length() - 1)); } } @FXML private void toggleSign(ActionEvent event) { String currentText = output.getText(); if (!currentText.isEmpty() && !currentText.equals("0")) { double currentValue = Double.parseDouble(currentText); currentValue = -currentValue; // Смена знак // Проверка, является ли число целым if (currentValue == (int) currentValue) { output.setText(String.valueOf((int) currentValue)); // Отображение как целое } else { output.setText(String.valueOf(currentValue)); // Отображение как вещественное } } } }
App
package org.example.demo; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.scene.layout.AnchorPane; import javafx.stage.Stage; import java.io.IOException; public class App extends Application { @Override public void start(Stage stage) throws IOException { FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource("calc.fxml")); Scene scene = new Scene(fxmlLoader.load(), 500, 550); stage.setTitle("Calculator"); stage.setScene(scene); stage.setResizable(false); stage.show(); } public static void main(String[] args) { launch(); } }
ConrollerTest
package org.example.demo; import javafx.application.Platform; import javafx.event.ActionEvent; import javafx.scene.control.Label; import javafx.scene.control.Button; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import static org.mockito.Mockito.*; class ControllerTest { @Mock private CalculatorClass ccMock = new CalculatorClass(); @Mock private CalculatorViewClass cvMock = new CalculatorViewClass("", ""); @Mock private CalculatorPresenterClass cpMock = new CalculatorPresenterClass(); @InjectMocks private Controller controller; @BeforeEach public void setUp() { MockitoAnnotations.openMocks(this); // Инициализация моков } @Test void testDisplayError() { controller.num1 = 1.0; controller.num2 = 0.0; controller.operatorVal = "/"; // Настройка поведения мока, чтобы он бросал исключение при вызове divide when(ccMock.divide(controller.num1, controller.num2)).thenThrow(new ArithmeticException("Значение второго аргумента b слишком мало: |b| < 10e-8")); controller.operatorAlternate(new ActionEvent()); controller.operatorValTest = "="; controller.operatorAlternate(new ActionEvent()); verify(ccMock).divide(controller.num1, controller.num2); // Проверка, что метод displayError был вызван с ожидаемым сообщением verify(cvMock).displayError("Полученная ошибка: Значение второго аргумента b слишком мало: |b| < 10e-8"); } @Test void testSumAndPrintResult(){ controller.num1 = 10.0; controller.num2 = 5.0; controller.operatorVal = "+"; when(ccMock.sum(controller.num1, controller.num2)).thenReturn(15.0); controller.operatorAlternate(new ActionEvent()); controller.operatorValTest = "="; controller.operatorAlternate(new ActionEvent()); verify(ccMock).sum(controller.num1, controller.num2); verify(cpMock).onPlusClicked(); verify(cvMock).printResult(15.0); } @Test void testSubtractAndPrintResult(){ controller.num1 = 10.0; controller.num2 = 5.0; controller.operatorVal = "-"; when(ccMock.subtract(controller.num1, controller.num2)).thenReturn(5.0); controller.operatorAlternate(new ActionEvent()); controller.operatorValTest = "="; controller.operatorAlternate(new ActionEvent()); verify(ccMock).subtract(controller.num1, controller.num2); verify(cpMock).onMinusClicked(); verify(cvMock).printResult(5.0); } @Test void testMultiplyAndPrintResult(){ controller.num1 = 10.0; controller.num2 = 5.0; controller.operatorVal = "*"; when(ccMock.multiply(controller.num1, controller.num2)).thenReturn(50.0); controller.operatorAlternate(new ActionEvent()); controller.operatorValTest = "="; controller.operatorAlternate(new ActionEvent()); verify(ccMock).multiply(controller.num1, controller.num2); verify(cpMock).onMultiplyClicked(); verify(cvMock).printResult(50.0); } @Test void testDivideAndPrintResult(){ controller.num1 = 10.0; controller.num2 = 5.0; controller.operatorVal = "/"; when(ccMock.divide(controller.num1, controller.num2)).thenReturn(2.0); controller.operatorAlternate(new ActionEvent()); controller.operatorValTest = "="; controller.operatorAlternate(new ActionEvent()); verify(ccMock).divide(controller.num1, controller.num2); verify(cpMock).onDivideClicked(); verify(cvMock).printResult(2.0); } }