LINUX.ORG.RU

Тестовое задание, где я ошибся?


0

2

Добрый день. Решил я тут отправить резюме в компанию N и выполнить их тестовое задание. Само задание

Есть интерфейс:

public interface Rtriangle {
int getApexX1();
int getApexY1();
int getApexX2();
int getApexY2();
int getApexX3();
int getApexY3();
}

Методы возвращают 6 чисел — координаты трех вершин прямоугольного треугольника в декартовой системе координат.

Есть метод, возвращающий прямоугольный треугольник:

public final class RtriangleProvider {
public static Rtriangle getRtriangle() {
...
}
}

Напишите код junit теста, который будет проверять, действительно ли метод 
getRtriangle возвращает прямоугольный треугольник.
А вот jUnit тест
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mariarti.Rtriangle;
import org.mariarti.RtriangleProvider;

import java.util.*;

public class T_Rtriangle {
    private Rtriangle rtriangle = RtriangleProvider.getRtriangle();
    private int
            x1 = rtriangle.getApexX1(),
            y1 = rtriangle.getApexY1(),
            x2 = rtriangle.getApexX2(),
            y2 = rtriangle.getApexY2(),
            x3 = rtriangle.getApexX3(),
            y3 = rtriangle.getApexY3();
    private double
            sideTriangleA,
            sideTriangleB,
            sideTriangleC;
    private final static double delta = 0.0000000001;
    private List<Double> legs = new ArrayList<>();

    @Before
    public void initTest(){
        legs.add(getLength(x1, y1, x2, y2));
        legs.add(getLength(x2, y2, x3, y3));
        legs.add(getLength(x3, y3, x1, y1));
        Collections.sort(legs);
        sideTriangleA = legs.get(0);
        sideTriangleB = legs.get(1);
        sideTriangleC = legs.get(2);
    }

    public double getLength(int x1, int y1, int x2, int y2){
        return Math.sqrt(Math.pow((x1 - x2), 2) + Math.pow((y1 - y2), 2));
    }

    @Test
    public void ACosTest(){
        double angleA = Math.acos(
                (Math.pow(sideTriangleB, 2) + Math.pow(sideTriangleC, 2) - Math.pow(sideTriangleA, 2))
                    / (2 * sideTriangleB * sideTriangleC));
        double angleB = Math.acos(
                (Math.pow(sideTriangleA, 2) + Math.pow(sideTriangleC, 2) - Math.pow(sideTriangleB, 2))
                    / (2 * sideTriangleA * sideTriangleC));
        double angleC = Math.acos(-1) - (angleA + angleB);
        Assert.assertEquals(Math.acos(0), angleC, delta);
    }

}
И меня слили. Господа, в чем я ошибся? Не могу ни спать ни есть пока не найду объяснений.



Последнее исправление: dr_mariarti (всего исправлений: 2)
Ответ на: комментарий от Hater

Так первый код и есть задание.

public final class RtriangleProvider {

    private static class inRtriangle implements Rtriangle{
        public int getApexX1(){
            return -1000000;
        }
        public int getApexY1(){
            return -1000000;
        }
        public int getApexX2(){
            return -1000000;
        }
        public int getApexY2(){
            return 9000000;
        }
        public int getApexX3(){
            return 6000000;
        }
        public int getApexY3(){
            return -1000000;
        }
    }

    public static Rtriangle getRtriangle() {
        return new inRtriangle();
    }

}
Моя «реализация» тестового задания выдает как раз прямоугольный треугольник.

dr_mariarti
() автор топика
Ответ на: комментарий от dr_mariarti

Странная контора, в которой в качестве тестового задания дают написание юнит-тестов.

Ну замечаний много можно написать, но как-то лень. Самое главное: тестируемый тобой метод дёргается за пределами метода теста.

Hater ★★
()
Ответ на: комментарий от Hater

double delta = 0.0000000001;

Кстати арифметику лучше вести в BigDecimal чтобы не трахать себе мозг проблемами машинного округления.

Hater ★★
()
Ответ на: комментарий от Hater

Да и в тестировании я слаб. Точнее, вообще первый раз нормально что то пишу. Спасибо большое! Можете порекомендовать литературу по этой теме?

dr_mariarti
() автор топика
Ответ на: комментарий от dr_mariarti

Легко: находишь какой-нибудь опенсорцный проект и читаешь тесты. Хотя конечно проект проекту рознь...

Hater ★★
()
Ответ на: комментарий от Hater

+ ещё можно было бы написать тест на воспроизводимость. Где гарантия, что 2 раз он кинет правильную фигуру?

Hater ★★
()
Ответ на: комментарий от Hater

«Какой-нибудь» не надо - порой можно такую лажу найти...

BattleCoder ★★★★★
()

Не знаю жабку и как правильно оформлять жуниты, но по-моему ты вместо того, чтобы заассертить sta^2 + stb^2 ~= stc^2, укатил в неведомые дали по вычислению каких-то углов. Учитывая, что в уравнении квадраты, проверка вообще становится почти тривиальной от входных, корни не нужны. Сравнение ты кажется провалил fuzz factor'ом (формулы не парсил, и в общем-то сам не помню, как допустимую погрешность вычислять, floating-point-gui.de).

arturpub ★★
()
Ответ на: комментарий от Hater

Входные уже в даблах, это если только с нуля юзать. Но какой смысл, если корень из двух все равно будет кривой?

arturpub ★★
()
Ответ на: комментарий от arturpub

Тут проблема в том, что на больших значениях терема Пифагора не катит. Слишком большие отклонения. А вот с теоремой синусов такой проблемы нет и delta = 0.0000000001 вполне достаточна.

dr_mariarti
() автор топика
Ответ на: комментарий от arturpub

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

Hater ★★
()
Ответ на: комментарий от dr_mariarti

Звучит логично, но у меня большие сомнения, что это не тот же ***, только в другой руке. Не будучи математиком, доказать разумеется не смогу.

arturpub ★★
()
Ответ на: комментарий от Hater

И еще за это спасибо. Банальная теорема Пифагора заработала без округления. Какой же я баран...

dr_mariarti
() автор топика

Все конторы в которых предлагают сделать тестовое задание - галимые шарашки ( размер штата не имеет значения )

Ты ошибся когда стал делать тестовое задание.

peacelove
()
Ответ на: комментарий от dr_mariarti

Ну, да. ПРопустил момент с sort.

anonymous
()

Кстати через скалярное произведение векторов было бы наверное самым труёвымЪ решением.

Hater ★★
()
Ответ на: комментарий от anonymous

Да отправил готовый вариант. Посмотрим, что из этого выйдет.

dr_mariarti
() автор топика

Стилистическое замечание: твой код читать сложно. Всё одним куском, длинные имена

KennyMinigun ★★★★★
()

Можно сделать проще и точнее: если скалярное произведение векторов на какой-нибудь паре отрезков равно нулю, то они перпендикулярны. Для этого ни разу не надо использовать арифметику с плавающей точкой.

BlackHawk
()

Особо не вчитывался, но вроде нет проверки на то, что возвращённые точки вообще образуют треугольник. Как поведёт себя тест, если например длина одной (или всех) сторон будет нулевой?

CARS ★★★★
()
Ответ на: комментарий от CARS

Пускай будет так.

import org.junit.Assert;
import org.junit.Test;
import org.mariarti.Rtriangle;
import org.mariarti.RtriangleProvider;

import java.math.BigDecimal;
import java.util.*;

public class T_Rtriangle {
    // Если хоть одна из сторон = 0, то и это не треугольник
    // Тест будет провален
    public BigDecimal getLongLengthPow2(int x1, int y1, int x2, int y2){
        BigDecimal res = new BigDecimal(x1 - x2).pow(2).add(new BigDecimal(y1 - y2).pow(2));
        Assert.assertNotEquals(res.intValue(), 0);
        return res;
    }

    @Test
    public void PifagotTest(){
        Rtriangle rtriangle = RtriangleProvider.getRtriangle();
        List<BigDecimal> legs = new ArrayList<>();
        int
                x1 = rtriangle.getApexX1(),
                y1 = rtriangle.getApexY1(),
                x2 = rtriangle.getApexX2(),
                y2 = rtriangle.getApexY2(),
                x3 = rtriangle.getApexX3(),
                y3 = rtriangle.getApexY3();

        legs.add(getLongLengthPow2(x1, y1, x2, y2));
        legs.add(getLongLengthPow2(x2, y2, x3, y3));
        legs.add(getLongLengthPow2(x3, y3, x1, y1));
        Collections.sort(legs);

        List<BigDecimal>bigDecimal = new ArrayList<>();

        BigDecimal angleA = legs.get(0);
        BigDecimal angleB = legs.get(1);
        BigDecimal angleC = legs.get(2);

        Assert.assertEquals(angleC, angleA.add(angleB));
    }
}

dr_mariarti
() автор топика

Зачем косинусы вместо c2=a2+b2?

g0t0
()

Ага, они воруют написанный сосикателями код и запиливают его в продакшен, прямо на сервера льют, как только письмо с выполненным тестовым заданием в почту прилетает.

Я 100 раз такое видел!

g0t0
()

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

Держи:

double innerProduct = (x2 - x1) * (x3 - x1) + (y2 - y1) * (y3 - y1);
Assert.assertEquals(0, innerProduct, delta);

Кроме того, зачем-то ты считаешь angleA и angleB, вместо того, чтобы сразу посчитать angleC.

Кроме того, если угол angleA окажется очень маленьким, то у тебя аргумент Math.acos может оказаться больше единицы из-за ошибок округления, и ты получишь runtime error, даже если тест мог пройти.

Наконец, они могли иметь в виду, что один из углов прямой — но не обязательно именно C.

Miguel ★★★★★
()
Ответ на: комментарий от Miguel

Ответ на двоечку. Дополнительный вопрос на троечку - перечислить все усдовия, при которых у тебя double переполнится и ты получишь неправильный ответ при правильных и легальных значениях координат вершин.

anonymous
()
Ответ на: комментарий от anonymous

Если у тебя переполняется double при вычислении скалярного произведения, то у тебя серьёзные проблемы в логике программы. Что-то вроде попыток использовать нанометры при работе в масштабах Солнечной системы.

anonymous
()
Ответ на: комментарий от anonymous

то у тебя серьёзные проблемы в логике программы.

А юнит-тесты для того и существуют, чтобы эти проблемы выявлять. Данный тест бесполезен, поскольку проблем не выявит.

anonymous
()
Ответ на: комментарий от anonymous

Потому что

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

peacelove
()
Ответ на: комментарий от dr_mariarti

на больших значениях терема Пифагора не катит.

что?

next_time ★★★★★
()
Ответ на: комментарий от dr_mariarti

А ещё это не треугольник, если все точки лежат на одной прямой.

kim-roader ★★
()
Ответ на: комментарий от dr_mariarti

А где гарантия того, что тебе вообще вернули треугольник? Я возьму и верну тебе 2 точки с одинаковыми координатами, ты и сядешь в лужу с поиском наибольшей стороны/наименьших сторон.

peregrine ★★★★★
()
Последнее исправление: peregrine (всего исправлений: 1)

На яве не пишу, хотя читать могу, потому ошибок в синтаксисе, если они у тебя есть не вижу. А теперь в логике (тут совсем плохо):

1) Что это за магическое число такое? За это по рукам бить надо.

[code]private final static double delta = 0.0000000001;[/code]

2) Сперва наперво, прежде чем что-то считать ты должен понять, а что тебе вернули? (ты же получил только координаты трёх точек, которые могут быть чем угодно, точкой, отрезком, треугольником). Для этого ты должен проверить, совпадают ли их вершины, и только, если все три вершины не совпадают, то ты должен писать тест дальше, притом из условия не сказано, что прямой угол C. Это может быть любой угол. Не думаю, чтобы тут так была необходима теорема синусов/косинусов, можно и по Пифагору посчитать, тем более тебе не предъявили требуемой точности «прямоугольности» твоего прямоугольного треугольника.

peregrine ★★★★★
()
Ответ на: комментарий от Miguel

Хороший ответ, мне нравится. Главное сначала удостовериться, что у тебя треугольник, а то ерунду получишь.

peregrine ★★★★★
()
Ответ на: Потому что от peacelove

А как еще оценивать жуниора, поступающего на первую работу, не имеющего опенсорсного кода?

staseg ★★★★★
()
Ответ на: Потому что от peacelove

ИМХО тест хорошо показал компетентность ТС-а (задачка простая, но ТС сфейлил). Ему надо развивать внимательность.

peregrine ★★★★★
()
Ответ на: комментарий от peregrine

ИМХО тест хорошо показал компетентность ТС-а

lol, так вон оно как компетентность то проверяют. По твоей логике 90-% ЛОРа - это некомпетентное быдло.

UVV ★★★★★
()
Ответ на: комментарий от UVV

Ну лично мне кажется, что ТС джуниор, хотя это вообще не имеет значения. Привожу цитату:

Все конторы в которых предлагают сделать тестовое задание - галимые шарашки

И мой вопрос к этому товарищу, как собственно компании тогда искать жуниора, если она не хочет упасть в глазах этого товарища до галимой шарашки?

staseg ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.