Если нельзя, но очень хочется, то нужно обязательно и ничего в мире не стоит того, чтобы делать из этого проблему!


Интересна Java? Кликай по ссылке и изучай!
Если тебе полезно что-то из того, чем я делюсь в своем блоге - можешь поделиться своими деньгами со мной.
с пожеланием
столько времени читатели провели на блоге - 
сейчас онлайн - 

понедельник, 12 марта 2012 г.

Java for fun: Что делать, если нет тестов

У меня на тренинге трейни пишут ООП модельки (университет там, жек). Работают в основном с консолью. System.out.println почти в каждом методе. Но тестов пока нет, потому как рано еще давать. Но мне, чтобы демонстративно порефакторить их код надо тесты. Как быть? Выход нашелся....

Студенты как-то интуитивно чувствуют, что нужен некий метод main в котором модель надо позапускать. Иногда даже называют этот класс тестовым. Вот пример такого класса
package ua.kpi.javatrainee6.model;
import ua.kpi.javatrainee6.model.departments.*;
import ua.kpi.javatrainee6.model.people.*;

public class UniversityModel {
 
    private static void testUniverFunctionality(University univer) {
        univer.viewAllSections();
        univer.viewAllSubjects();
        univer.viewAllMembers();
        univer.viewCurriculum();
    }
 
    private static void testGroupFunctionality(Group group) {
        group.viewAllSections();
        group.viewAllMembers();
        group.viewAllSubjects();
        System.out.printf("Average score of group = %1.2f\r\n", group.calculateAverage());
        group.viewCurriculum();
    }
 
    private static void testAdminFunctionality(UniversityAdministrator admin) {
        admin.viewResponsibilities();
        admin.performAssessment();
        System.out.println("Results of assessment");
        for (Group group : admin.getGroups()) {
            System.out.println("For group " + group.getTitle());
            for (Student student : group.getStudents()) {
                student.viewAllMarks();
            }
        }
        System.out.println("Salary: " + admin.calculateSalary());
    }
 
    private static void testProfessorFunctionality(Professor professor) {
        professor.viewResponsibilities();
        professor.viewAllGroups();
        professor.viewCurriculum();
        System.out.println("Salary: " + professor.calculateSalary());
        professor.evaluateAsBadOrGood();
    }
 
    private static void testStudentFunctionality(Student student) {
        student.viewResponsibilities();
        student.viewAllMarks();
        System.out.printf("Average score of student = %1.2f\r\n",     student.calculateAverage());
        student.viewCurriculum();
        System.out.println("Salary: " + student.calculateSalary());
        student.evaluateAsBadOrGood();
    }
 
    public static void main(String[] args) throws IOException {
        University univer = new University("KPI", new Date());
        testUniverFunctionality(univer);

        UniversityAdministrator admin = univer.getAdmin();
        testAdminFunctionality(admin);

        Professor anyProfessor = admin.getProfessors().get(0);
        testProfessorFunctionality(anyProfessor);

        Group anyGroup = admin.getGroups().get(0);
        testGroupFunctionality(anyGroup);

        Student anyStudent = anyGroup.getStudent(0);
        testStudentFunctionality(anyStudent);
    }
}
В университете каждый univer.viewBlaBla() метод печатает что-то на консоль. Инкапсулировать System.out в одном месте задача сложновастая - могу что-то поломать.

Что было сделано. Переоперделил консольку и записал результаты в файл.
...
    public static void main(String[] args) throws IOException {
        ByteOutputStream out = switchSystemOut();

        // тут без изменений

        wtiteTo(out, "1.txt");
    }

    private static void wtiteTo(ByteOutputStream out, String name) throws IOException {
        File path = new File(name);
        path.createNewFile();
        FileOutputStream file = new FileOutputStream(path);
        out.writeTo(file);
        file.close();
    }
}

Считается что там все сейчас работает, а потому делается такой вот фикс
...
    public static void main(String[] args) throws IOException {
        ByteOutputStream out = switchSystemOut();

        // тут без изменений

        String expected = readFrom("1.txt");
        if (!expected.equals(out.toString())) {
            throw new Error("Я чёта поламал!!");
        }
    }

    private static ByteOutputStream switchSystemOut() {
        ByteOutputStream out = new ByteOutputStream();
        System.setOut(new PrintStream(out));
        return out;
    }

    private static String readFrom(String name) throws IOException {
        File path = new File(name);
        InputStream reader = new BufferedInputStream(new FileInputStream(path));
        byte[] data = new byte[reader.available()];
        reader.read(data);
        reader.close();
        return new String(data);
    }
}
Читаем из файла и сравниваем с той же консолькой. Если не equals - значит что-то поломал.

Чем не инструмент? Мне помог.

Да, кстати. Чтобы он помог надо рефакторингом пользоваться осторожно. Делаем небольшое изменение так, чтобы компиляция как можно быстрее прошла. Запускаем "main-тест" и если все ок - коммитимся! Потом проделываем ту же операцию. Если не дай бог тест не проходит - делаем откат и перерыв. Потом снова подходим к коду и пробуем, но уже аккуратнее, сделать то же. Не дебажим!

2 комментария:

  1. Знаем такое, юзали. Классная идея. Пахнет правда... как и то, что я предложил...

    ОтветитьУдалить