Re[4]: Как важно проверять в программах ошибки до конца
От: Eugeny__ Украина  
Дата: 20.06.12 21:58
Оценка:
Здравствуйте, мыщъх, Вы писали:

М>проблема несколько глубже. результаты уже на лице -- в жабе стало нельзя легально прибивать потоки без участия с их стороны. допустим, мы вызвали скрипт манагер из жабы, который вызывает жаба-скрипт, контролируемый юзером/хакером. допустим, в жаба-скрипте while(1); -- в результате поток висит. легально снять -- нельзя. нелегально можно, но это уже хак.


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


М>если брать обработку исключений в венде, то там можно обнаружить два уровня. первый уровень -- это когда стек уже кончился, но запас по прочности еще есть. в этом момент выбрасывается нормальное исключение о том, что стека нет (на самом деле есть, но мало). фишка в том, что повторно это исключение уже не вызываается и когда стек заканчивается, то он заканчивается, а обработчик исключений требует стека для себя любимого, а стека у нас нет. в XP в этом случае винда вела себя... мягко говоря не совсем так, как описано в документации. процесс умирал в ядре без освобождения ресурсов (точнее, с негарантированным их освобождением). в семерке уже пофиксили это и добавили (грубо говоря) еще один уровень "finally" (в кавычках, потому что finally пришел из плюсов, но его концепция намного шире) и теперь у нас есть (грубо говоря) процедура аварийного завершения процесса (ядерная) и процедура аврального аварийного завершения процесса. разница между ними в том, что одна из них _гарантирует_ выполнение finally, а другая всего лишь намеревается это сделать.


М>как бы наивно предполгать, что try...finally работает. оно не работает. оно лишь предполагает. а бог располгает. библиотечные функции, родные для данной системы, скорее всего, придерживаются try...finally (если в спецификации не оговорено обратное), но как поведет себя произвольная функция -- сказать нельзя, особенно если эта функция древняя и оставлена только для совместимости.


В жабе проще. Там стек-то не нативный, и исключение полетит и обработается в любом случае(не тобой, так штатным обработчиком, установленным для этого потока, по умолчанию это вывод трейса в stderr). Потому можно не париться техническими трудностями: для исключения стека всегда хватит.
Новости очень смешные. Зря вы не смотрите. Как будто за наркоманами подсматриваешь. Только тетка с погодой в завязке.
There is no such thing as a winnable war.
Re[4]: Как важно проверять в программах ошибки до конца
От: quwy  
Дата: 20.06.12 22:24
Оценка: -1
Здравствуйте, Deprivator, Вы писали:

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

Однажды, очень давно, довелось мне написать это:
function ClipperCRC(const Stream: TStream): Cardinal;
label
  ReadLoop, DataLoop, ProcEnd;
var
  CPU: packed record
    SI, DI, BP: Word;
    DS: array[1..512] of Byte;
  case Byte of
    0: (AL, AH, DL, DH, BL, BH, CL, CH: Byte);
    1: (AX, DX, BX, CX: Word);
    2: (AXDX, BXCX: Cardinal);
  end;
begin
  Stream.Position:= 0;
  with CPU do
    begin
      BP:= 0;
      DI:= 0;
      ReadLoop:
      CX:= SizeOf(DS);
      AX:= Stream.Read(DS, CX);
      if AX = 0 then goto ProcEnd;
      DI:= DI+AX;
      CX:= AX-1;
      SI:= 1;
      AX:= 0;
      DataLoop:
      AX:= AX+PWord(@DS[SI])^; // add AX, [DS:SI]
      Inc(SI);
      if CX > 1 then // loop DataLoop
        begin
          Dec(CX);
          goto DataLoop;
        end
      else
        CX:= 0;
      BP:= BP+AX;
      AL:= DS[SI];
      AH:= DS[SI];
      Inc(SI);
      BP:= BP+AX;
      AX:= BP;
      DX:= DI;
      AXDX:= AX*DX; // mul DX
      BP:= BP+AX;
      if BP = 0 then Inc(BP);
      goto ReadLoop;
      ProcEnd:
      DX:= DI;
      AX:= BP;
    end;
  Result:= CPU.AXDX;
end;

Откуда взялся этот код и почему он выглядит именно так, должно быть понятно любому здесь. Расскажите неграмотному дельфисту что-нибудь про формошлепство и непонимание внутреннего устройства компьютера.
Re[5]: Как важно проверять в программах ошибки до конца
От: мыщъх США http://nezumi-lab.org
Дата: 20.06.12 23:10
Оценка:
Здравствуйте, Eugeny__, Вы писали:

E__>Здравствуйте, мыщъх, Вы писали:


E__>Что в данном случае означает "вызвали скрипт манагер из джавы"?

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

берем код вида:
ScriptEngine js = new ScriptEngineManager().getEngineByName("js");
FileReader f = new FileReader(args[0]); js.eval(f); f.close();

считаем, что в файле может быть 'while(1);' или какие другие подлянки. наша задача -- выполнить скрипт или спустя 500 ms послать скрипт на юг и вернуть ошибку, освободив все ресурсы.

> Если это внешний процесс, то остановить его очень легко.

это ScriptEngineManager из JRE. его можно остановить без ругательств со стороны компилятора? я пробовал и так, и сяк -- компилятор выдает предупреждение, что и то, и се уже давно как deprecated и потому такое решение не пропускает QA (и правильно делает).

E__>В жабе проще. Там стек-то не нативный, и исключение полетит и обработается в любом случае

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

и потому я вполне могу вообразить ситуацию, когда вызов super_lib.super_exit(0) вызовет API оси, а ось не знает, что мы должны выполнить какой-то код перед завершением. вся надежда на автора библиотеки super_lib. надежда, как вы понимаете, слабая. пример тому -- ошибки переполнения нативного стека в штатных библиотеках. если авторы java так косячат, чего ожидать от каких-то студентов, пишуших библиотеки в гараже у которых даже QA нет.

> Потому можно не париться техническими трудностями: для исключения стека всегда хватит.

лень вспоминать cve номер ошибки переполнения стека. нативного. кажется в 2008 или в 2009 году нашли. там короче когда вызывается апплет и создается поток и переполняется стек, то выскакивает исключение, которое ловится и подавляется. затем стек переполняется еще раз. на этот раз винда уже убрала сторожевую страницу и выскакивает или исключение доступа или мы врезаемся в стек другого потока. так из одного потока можно воздействовать на стек другого. а к чему это приводит... теоритически можно лихо подменять практически любые данные. практически хакеры не ушли дальше крэша. но это потому что на тот момент в хакерскую индустрию еще не хлынули миллионы криминальных долларов и никому было не интересно реализовать атаку на банк клиент, например.

java, как ни крути, исполняется на нативном стеке. и java-машина не свободна от ошибок. давайте зададимся вопросом -- что произойдет, если выполнение библиотечной функции приведет к переполнению нативного стека? и как java-программист может обработать такую ситуацию или предотвратить ее? на винде в нативном си коде я могу. даже очень могу. я просто поставлю свою сторожевую страницу, зарезервировав для своих нужд пол-метра памяти. это хватит с головой, чтобы корректно обработать любую ситуацию -- сделать откат или по крайней мере сохранить все данные и корректно завершиться. и мне наплевать на библиотеки. пускай делают, что хотят. навряд ли кто-то полезет в стек искать "левую" сторожевую страницу и специально ее снимать (это уже умышленное вредительство).
americans fought a war for a freedom. another one to end slavery. so, what do some of them choose to do with their freedom? become slaves.
Re[5]: Как важно проверять в программах ошибки до конца
От: мыщъх США http://nezumi-lab.org
Дата: 20.06.12 23:18
Оценка: :)
Здравствуйте, quwy, Вы писали:

Q>Здравствуйте, Deprivator, Вы писали:


Q>Откуда взялся этот код и почему он выглядит именно так, должно быть понятно любому здесь.

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

программы на дельфи я узнаю сразу. в них хронически не работает tab или скачет между полями не в том порядке в котором они на экране. дельфисты не читают гайдлайнов. когда я такое увидел на webmoney, то с этой конторой мне сразу стало все ясно. это октябрята, которых не взяли в пионеры. удивительно, но в среде того же ms vs такое встречается значительно реже и tab'ы работают как надо. не потому что это среда обеспечивает (не обеспечивает она этого), а потому что порог вхождения выше.
americans fought a war for a freedom. another one to end slavery. so, what do some of them choose to do with their freedom? become slaves.
Re[4]: Как важно проверять в программах ошибки до конца
От: мыщъх США http://nezumi-lab.org
Дата: 20.06.12 23:24
Оценка:
Здравствуйте, Eugeny__, Вы писали:

E__>Здравствуйте, alzt, Вы писали:



E__>The finally block always executes when the try block exits.

см. выделенное. вы не анализировали малварь на java. там хорошая традиция -- не выполнять finally, перепрыгивая через него. кстати, делается легально средствами самой java без всяких там хаков. декомпиляторы с ума сходят -- control flow хрен построишь.
americans fought a war for a freedom. another one to end slavery. so, what do some of them choose to do with their freedom? become slaves.
Re[6]: Как важно проверять в программах ошибки до конца
От: quwy  
Дата: 20.06.12 23:33
Оценка: +1
Здравствуйте, мыщъх, Вы писали:

Q>>Откуда взялся этот код и почему он выглядит именно так, должно быть понятно любому здесь.

Q>>Расскажите неграмотному дельфисту что-нибудь про формошлепство и непонимание внутреннего устройства компьютера.
М>извините, но у вас ноги из попы растут.
Ваше мнение озвучено, но отвергнуто как несостоятельное. До свидания.
Re[7]: Как важно проверять в программах ошибки до конца
От: мыщъх США http://nezumi-lab.org
Дата: 20.06.12 23:45
Оценка:
Здравствуйте, quwy, Вы писали:

Q>Здравствуйте, мыщъх, Вы писали:


Q>>>Откуда взялся этот код и почему он выглядит именно так, должно быть понятно любому здесь.

Q>>>Расскажите неграмотному дельфисту что-нибудь про формошлепство и непонимание внутреннего устройства компьютера.
М>>извините, но у вас ноги из попы растут.
Q>Ваше мнение озвучено, но отвергнуто как несостоятельное. До свидания.
обосновать сможете? ну или давайте письками меряться. если мой код на паскале будет работать сильно медленнее вашего асма -- считайте, что у вас длинеее. и, соответственно, наоборот. код тот же что и у вас (по функционалу), компилятор -- аналогично. незнание матчасти, незнание принципов построения осей и компиляторов и прочего фундаментализма не позволяет вам решать задачи на паскале без тормозов.
americans fought a war for a freedom. another one to end slavery. so, what do some of them choose to do with their freedom? become slaves.
Re[8]: Как важно проверять в программах ошибки до конца
От: quwy  
Дата: 21.06.12 00:03
Оценка:
Здравствуйте, мыщъх, Вы писали:

М>>>извините, но у вас ноги из попы растут.

Q>>Ваше мнение озвучено, но отвергнуто как несостоятельное. До свидания.
М>обосновать сможете?
Весь ваш пост построен на эмоциях, а не на здравом смысле. Вы не поняли ни задачи, породившей данный код, ни его назначения. Вы сделали необоcнованные заявления. И вообще, вы сильно разочаровали, Николай. Похоже вы больше пиарщик, чем айтишник.

Я не собираюсь ни с кем меряться пиписьками и соревноваться в скорости программ, результаты моего давнего кодинга есть мой сегодняшний доход, и он меня полностью устраивает.
Re[9]: Как важно проверять в программах ошибки до конца
От: landerhigh Пират  
Дата: 21.06.12 00:31
Оценка:
Здравствуйте, Michael7, Вы писали:

M>Здравствуйте, landerhigh, Вы писали:



L>> Написать тест, проверяющий поведение его супер-функции при корректных, некорректных и граничных вхожных данных заняло бы две минуты. Ладно, это у меня. У ТС — ну полчаса максимум. Сколько у него там на отладку ушло времени? Вот то-то и оно.


M>Тогда немного опишу, что же именно некорректного было в данных. У меня функция заносит в БД извлеченное и обработанное содержимое некоторых файлов внутри *.zip -файлов, при этом естественно проверяет на корректность и само содержимое обрабатываемых файлов и формат и тд. При этом в редких случаях внутри *.zip-файла может быть еще вложенные *.zip-файлы и их тоже надо распаковать и в свою очередь проверить, что внутри. Вложенный файл я обрабатывал просто рекурсивным вызовом.


Ой, уже звучит страшно. Не слишком ли много для одной функции? Хотя, если она внутри выглядит примерно так


binaryStream Unpacked = ZipTools::Unpack(PackedData);
m_dbProvider->UpdateMyCoolDataSet(ExtractData(Unpacked));


то все еще пучком.

M>Тесты (просто набор разных исходных данных) есть, все ситуации с ошибками тестировали и они обрабатывались, программа не падала.


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


M> Но забыли протестировать случай, когда такая ошибка возникает при работе с содержимым внутри вложенного файла. То есть, неправильная работа с exit не приводила почему-то к падениям, пока работа шла на первом уровне вложенности. Я и говорю, что диспетчер памяти оказался склонным прощать некоторые ошибки в работе с ней. Падать стало внутри рекурсии.


привычка писать юнит-тесты доводит до того, что программист органически становится неспособным "забыть" протестировать такие. То есть написать тест, покрывающий подобную ситуацию воспринимается как нечто само собой разумеющееся и никаких вопросов не вызывает.
Кроме того, написать юнит-тест, проверяющий корректность работы и непадучесть этой функции, примерно в 10 тысяч раз легче, нежели тестировать ее корректное поведение на этапе QA. И выгоднее.

M>Программу я уже не трогал с год, просто все это время не случалось такого редкого сочетания с ошибкой.


А сколько еще подобных мест в вашем коде?
www.blinnov.com
Re[9]: Как важно проверять в программах ошибки до конца
От: landerhigh Пират  
Дата: 21.06.12 01:13
Оценка: 1 (1)
Здравствуйте, мыщъх, Вы писали:


М>единица вам. "are you writing..." вы пишите тест _одновременно_ с чтением форума. вы юлий цезарь?

М>Present Perfect Tense переводится как "вы _когда_ _либо_ писали тесты?". по аналогии I've been in London. это отличается от I was in London. в первом случае это "у меня есть жизненный опыт и я знаю что такое Лондон не только по картинкам", во втором случае вы просто там были. например, вас спрашивают -- какого хрена вас вчера не было на рабочем месте. а вы отвечаете: I was in London.

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

L>> При всем уважении, ты пытаешься лезть в область, в которой нихрена не понимаешь.

L>> Это я про тестирование. Я даже не знаю, с чего начать, чтобы объяснить глубину
М>с критическими инфраструктурами я не сталкивался и как там тестируют по — хз, но энерпрайз и военка -- это для меня ежедневная рутина. показывать им юнит тесты все равно что показывать палец. юмора не поймут и слив защитан.

Еще раз — ты пытаешься рассуждать на тему, в которой нихрена не понимаешь. Юнит-тест — это инструмент разработки. Его клиентам не показывают. Игнорирование этого мощного инструмента разработки привело к тому, что ТС пришлось убить кучу времени на пошаговую отладку. Я бы вообще отбирал у программистов отладчик на время разработки.

М>повторяю еще раз -- тест должен _доказать_ полноту и непротиворечивость. преобразование программы в диаграмму типа flow chart с последующей верификацией позволяет _доказать_, что она корректна (тут кажется кто-то упоминал светофор в качестве примера, кажется в контексте дракона. существуют системы верификации по, доказывающие, что два зеленых света гореть не могут. а доказать это можно если перевести ваш юнит в fsm, но это не юнит тест, это _совсем_ другое).


Это ты сейчас с кем разговариал? И, пожалуйста, не упоминай конечные автоматы в суе и особенно в разговорах со мной. Порву на лоскуты размером в атом, а из того, что осталось, вызову цепную ядерную реакцию.

>> У нас требуются сертифицированные перчатки другой системы

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

К счастью, никакое ISO не регламентирует, как именно должны тестироваться элементы ПО. И опять же, не путай UAT и FAT c тестированием во время разработки. Ты можешь построить хоть стопицот формальных моделей, потратить полгода на FAT и успешно пройти его, и все равно можешь жидко обосраться на второй день после запуска в эксплуатацию. Доказательство элементарно — твой софт состоит сплошь из функций, которые принимают какие-то входные значения, что-то с ними делают и выдают результат. Утрировано, конечно, но это так. Каждая их таких функций имеет следующие подмножества входных параметров — корректные, некорректные и граничные. Тебе, помимо функционального тестирования (проверить, что функция делает именно то, что должна), нужно проверить корректность поведения этой функции на этих наборах параметров. То есть на каждую функцию нужно еще три теста (три набора тестов, если быть точным, но в данном контексте это неважно). Соответственно, если у тебя 1000 функций, то тебе понадобится 3000 тестов, по грубой оценке.
Но! Если ты забъешь на юнит-тестирование, и будешь пытаться тестировать всю систему целиком как чОрный йащег (с), то тебе для достижения того же уровня покрытия, критериев этих и собственно, тест кейсов, понадобится минимум 3^1000. Удачи, как говорится, и заодно слив защитан.

М>еще раз. снимите розовые очки. посмотрите хотя бы на ошибки в ракетной технике, ошибки в медицинском оборудовании... при этом комплексы по тестированию этого самого оборудования это отдельные проекты. почитайте книгу inside intel -- там описано как параллельно с разработкой цп разрабатывались системы их тестирования. почитайте статью "редкая профессия" о том как писался компилятор и параллельно с ним писались тесты другой группой девов и сравните их бюджеты.


Дорогой, ты только что привел примеры двух индустрий, где юнит-тестирование проводится практически везде. Изготовление электронных компонентов, например. Каждый из них тестируется на сходе с конвеера. Каждая плата проходит электрический тест. Каждая собранная плата проходит как минимум базовый функциональный тест до установки ее в систему. Тестирование осуществляется на каждом этапе, где это только возможно автоматизировать. Там, где автоматизировать поленились или ошиблись с определением критериев, отрастают проблемы. То, что все равно есть ошибки — это всего лишь результат сложности системы. Если бы производители резисторов не тестировали их, то никакой ракетной техники бы не было вообще.

L>> Списывание отсутствия тестов на недостаточность ресурсов — это безоговорочное

L>> признание в собственной некомпетентности и прямая путевка за кассу в Макдональдс.
М>пытаюсь объяснить еще раз -- сложность _полного_ теста намного превышает сложность того, что мы тестируем. откроейте глаза и посмотрите на то, что вас окружает. начиная с программного обеспечения и заканчивая медикаментами. далеко не все это тестируется, а если и тестируется, то неполно и поверхностно. ракетно-космическая техника тестируется лучше, чем гражданская авиация, а гражданская авиация тестируется лучше, чем бытовой софт. а если бытовой софт тестировать по полной программе, то это все равно не гарантирует отсутствие ошибок, но цена ms office перевалит за миллиард баксов за одну лицензию. что вы курили?

Уважаемый, ты заговариваешься. Военная ракетная техника изначально тестировалась исключительно на полигоне. Но все очень быстро поняли, что, во-первых, восстанавливать полигон после каждого неудачного запуска не хватит ни одного военного бюджета, а, во-вторых, выяснять, что именно пошло не так, имея в наличии лишь оплавленный и спекшийся песок полигона, не очень продуктивно. Именно поэтому ракетные двигатели тестируются на стендах. И вся их обвязка тоже. Это и есть юнит-тестирование. Это, конечно, не узбавляет от катастроф на 100%, но уменьшает их вероятность на много порядков.

>> Сколько у него там на отладку ушло времени? Вот то-то и оно.

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

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

L>> Далее, факториал, точнее, то, что принято называть факториалом, на C++ вычисляется в compile time.

М>см. определение из вики. см. функцию факториала из гну либы на gcc.

L>> Его можно тестировать, но смысла особого нет.

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

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

L>> Но и твою притянутую за уши реализацию гамма-функции я тоже протестирую,

М>она не моя. она из 18 века вообще-то. а сейчас 21 век. столько не живут ИМХО.

L>> но при одном условии — если ты асилишь обозначить четкие критерии ее использования в программе,

М>лопата! вот у вас есть библиотечная гамма-функция. а она у вас есть (если под никсы пишите). и у вас возникает вопрос -- как быстро она работает? насколько сильно ошибается? вы хотите знать подходит ли она вам или нет. у вас есть требования по точности и времени. известны и целевые платформы. дело за малым -- убедиться, что все воркается. и вот тут выясняется, что тестирование функции которая заведово работает выливается в сложную инженерную задачу...

Тебе про Фому, а ты про Ерему.

L>> Если этого нет, то разочарую тебя — прикладной аналитикой занимаются на другом этаже.

М>вот он -- момент просветления. на уровне юнит-теста вы не можете сказать какие у вас требования к данной функции. допустим, время отклика системы должно быть не хуже 15 ms на таком-то железе. это во всей совокупности.

Сейчас ты лезешь в розетку с амперметром.
www.blinnov.com
Re[9]: Как важно проверять в программах ошибки до конца
От: landerhigh Пират  
Дата: 21.06.12 01:46
Оценка: :)
Здравствуйте, Fantasist, Вы писали:


L>>При всем уважении, ты пытаешься лезть в область, в которой нихрена не понимаешь. Это я про тестирование. Я даже не знаю, с чего начать, чтобы объяснить глубину твоего заблуждения, и считаю, что будет просто честным предложить оставаться тебе в своем хакерском R&D мире и не лезть в инженерные задачи в своих латексных перчатках. У нас требуются сертифицированные перчатки другой системы, и несоблюдение техники безопасности бывает фатальным.


F> Мне, на самом деле, давно интересно собрать статистику, сколько раз regression unit tests вылавливало ошибки, сколько раз после успешного тестирования ошибки все равно обнаруживались и сколько раз test failures ловили ошибки кода, а не теста.


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

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

F> Потому что в теории это классная вещь — написали тесты и теперь никто не изменит так, что оно перестанет работать. В практике я ни разу еще не видел, чтобы это работало. Создание хороших тестов работа более трудозатратная, сложная и высококвалифицированная нежели создание самого кода для бизнес логики. Но даже с хорошими тестами все равно ошибки возможны. И затраты на поддержание онных достаточно велики.


Нет никаких затрат на поддержание тестов. Если они есть, вы что-то делаете неправильно. Это мое профессиональное мнение, основанное на десятках коммерческих проектов.

F> Там где высокая надежность важна, применяются совем другие методы тестирования. Обычно этим занимается отдельная группа людей.


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

F> Но даже в более менее обычных бизнес-приложениях грамотный QA по фактору количество пойманных багов и количеству затраченных ресурсов работает значительно эффективней юнит тестов.


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

F>Это наблюдения из практики как она есть — никаких теорий.


Моя наблюдения из практики почему-то своершенно другие.
Вот моги главные замеченные отличие проектов, написанных в стиле "тесты писать некогда, нужно копать" от тех, где тесты, и много, были написаны:

1. проекты, где юнит-тестирование применялось првильно и в полный рост, чаще всего оказываются code complete и feature complete еще до дедлайна, в то время, как проекты без юнит-тестирования без исключений залезают крепко за дедлайн
2. Ошибки, найденные во время QA на проектах, покрытых юнит-тестами, разительно отличаются от ошибок, найденных на классических проектах. Обычно они лежат в плоскости "а мы считаем, что здесь спеки требуют другого поведения" и "поведение соответствует спекам, но заказчик понял, что ошибся в спеках и поэтому поведение нужно изменить", в то время как багрепорты от QA на классических проектах пестрят "упало", "не работает вообще", "сожрало всю память и опять упало" и прочими WTF.
3. Проекты, покрытые юнит-тестами, намного более гибкие в смысле дальшейшего развития и обеспечивают возможность легкого рефакторинга.
4. Из юнит-тестов можно вычленять автоматические функциональные тесты, облегчая работу QA
www.blinnov.com
Re[10]: Как важно проверять в программах ошибки до конца
От: мыщъх США http://nezumi-lab.org
Дата: 21.06.12 02:49
Оценка:
Здравствуйте, landerhigh, Вы писали:

L>Здравствуйте, мыщъх, Вы писали:


L>здесь. Дальше распространяться на эту тему не буду,

и что там по ссылке? и где я там не прав?

L> но даже по-русски будет корректнее спросить "а пишете ли вы вообще тесты",

"вы тесты писали" --> "занимались ли вы когда либо написанием тестов". что не так?

L> потому что любое прошедшее время подразумевает, что тесты писали, и, возможно, прекратили.

возможно и прекратили. возможно и нет. но если писали, то опыт остался даже если прекратили.

L> Еще раз — ты пытаешься рассуждать на тему, в которой нихрена не понимаешь.

это не аргумент. тоже самое я могу сказать о вас.

L> Юнит-тест — это инструмент разработки. Его клиентам не показывают.

привести примеры когда показывают? из того, что доступно в иннете? так кто из нас двоих ни хрена не понимает?

L> Игнорирование этого мощного инструмента разработки привело к тому,

L> что ТС пришлось убить кучу времени на пошаговую отладку. Я бы вообще
L> отбирал у программистов отладчик на время разработки.
согласен на счет отладчика. не согласен на счет теста. отладочная печть и логи -- чем не вариант?

L> И, пожалуйста, не упоминай конечные автоматы в суе и особенно в разговорах со мной.

L> Порву на лоскуты размером в атом, а из того, что осталось, вызову цепную ядерную реакцию.
стадию перехода на личности мы уже миновали и вот уже добрались до прямых угроз. давайте, рвите. мне и правда интересно

L> К счастью, никакое ISO не регламентирует, как именно должны тестироваться элементы ПО.

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

L> Доказательство элементарно — твой софт состоит сплошь из функций,

кто-то обещал порвать меня на автоматы. интересно, сколько у нас функций в DFA-дереве?

L> которые принимают какие-то входные значения, что-то с ними делают и выдают результат.

L> Утрировано, конечно, но это так. Каждая их таких функций имеет следующие подмножества
L> входных параметров — корректные, некорректные и граничные.
_каждая_ ?! вы в этом уверены?! функций без аргументов уже не бывает? my_pi() — какие тут аргументы? даже утрированно? какие некорректные аргументы у функции abs?!

L> То есть на каждую функцию нужно еще три теста (три набора тестов, если быть точным,

L> но в данном контексте это неважно). Соответственно, если у тебя 1000 функций,
L> то тебе понадобится 3000 тестов, по грубой оценке.
вы снова соглашаетесь со мной, что исчерпывающий тест намного больше по объему кода и по трудоемкости написания, чем то, что он тестирут. модели для других целей строят. например, если это пульт управления микроволновой печи -- модель _доказывает_, что нельзя войти в меню из которого потом не выйти. именно, что _доказывает_, причем верификация осуществляется автоматически.

L>Дорогой, ты только что привел примеры двух индустрий,

L>где юнит-тестирование проводится практически везде.
и обе индустрии вбухивают в тестирование мегабабло. потому что цена ошибки дороже.

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


L>Я тебе посоветую не разрабатывать программно-аппаратный комплекс,

L>так как из твоих слов понятно, что ты в этой теме ни бум-бум.
кто-то грозился отобрать отладчик...

L> Сейчас ты лезешь в розетку с амперметром.

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

вы так и не ответили на вопрос -- как убедиться в том, что в тесте нет ошибок?
americans fought a war for a freedom. another one to end slavery. so, what do some of them choose to do with their freedom? become slaves.
Re[11]: Как важно проверять в программах ошибки до конца
От: landerhigh Пират  
Дата: 21.06.12 04:19
Оценка: -1
Здравствуйте, мыщъх, Вы писали:

М>Здравствуйте, landerhigh, Вы писали:


L>>Здравствуйте, мыщъх, Вы писали:


L>>здесь. Дальше распространяться на эту тему не буду,

М>и что там по ссылке? и где я там не прав?

Пункт 2.

L>> но даже по-русски будет корректнее спросить "а пишете ли вы вообще тесты",

М>"вы тесты писали" --> "занимались ли вы когда либо написанием тестов". что не так?

Не так. Изначально не тот посыл. Некрасивый и заставляет оправдывться. Вроде "вы уже перестали бить свою жену по выходным".

L>> потому что любое прошедшее время подразумевает, что тесты писали, и, возможно, прекратили.

М>возможно и прекратили. возможно и нет. но если писали, то опыт остался даже если прекратили.

У 80% тех, у кого опыт остался, но прекратили, опыт этот сугубо отрицательный. Потому что писали из-под палки и только потому, что заставлял менеджер.

L>> Еще раз — ты пытаешься рассуждать на тему, в которой нихрена не понимаешь.

М>это не аргумент. тоже самое я могу сказать о вас.

Все приведенные тобой примеры не имеют никакого отношения к прадигме и предназначению юнит-тестирования.

L>> Юнит-тест — это инструмент разработки. Его клиентам не показывают.

М>привести примеры когда показывают? из того, что доступно в иннете? так кто из нас двоих ни хрена не понимает?

показывают, когда клиент явно просит, чего тут непонятного?

L>> Игнорирование этого мощного инструмента разработки привело к тому,

L>> что ТС пришлось убить кучу времени на пошаговую отладку. Я бы вообще
L>> отбирал у программистов отладчик на время разработки.
М>согласен на счет отладчика. не согласен на счет теста. отладочная печть и логи -- чем не вариант?

Сравниваешь теплое с мягким. Тесты выполяются автоматически во время каждого билда, и отладочная печать и логи по сравнению с ними находятся в одином ряду с каменным топором по сравнению с современным станком с ЧПУ.

L>> И, пожалуйста, не упоминай конечные автоматы в суе и особенно в разговорах со мной.

L>> Порву на лоскуты размером в атом, а из того, что осталось, вызову цепную ядерную реакцию.
М>стадию перехода на личности мы уже миновали и вот уже добрались до прямых угроз. давайте, рвите. мне и правда интересно

А вот не надо было соскользывать с темы и приплетать FSM куда не надо.

L>> К счастью, никакое ISO не регламентирует, как именно должны тестироваться элементы ПО.

М>у него еще и номер круглый. если вы хоть однажды в него заглядывали, то должны помнить.

Этот ISO — он для менеджеров. Которые программировать не умеют.

L>> Доказательство элементарно — твой софт состоит сплошь из функций,

М>кто-то обещал порвать меня на автоматы. интересно, сколько у нас функций в DFA-дереве?

Я нигде не говорил, что я телепат.

L>> которые принимают какие-то входные значения, что-то с ними делают и выдают результат.

L>> Утрировано, конечно, но это так. Каждая их таких функций имеет следующие подмножества
L>> входных параметров — корректные, некорректные и граничные.
М>_каждая_ ?! вы в этом уверены?! функций без аргументов уже не бывает? my_pi() — какие тут аргументы? даже утрированно? какие некорректные аргументы у функции abs?!

Хорошо, какой-то процент функций явных аргументов иметь не будет. Зато половина из них будет иметь контекст (глобальный или своего объекта), и зависимости от него тоже нужно тестировать.

А про abs(float) можешь начинать считать лоскуты. Граничные и специальные условия:

1) Проверка поведения при -0
2) проверка поведения при обоих NaN
3) Проверка, что никакой чертовщины с потерей точности не происходит

Это то, что пришло мне в голову за одну секунду.



L>> То есть на каждую функцию нужно еще три теста (три набора тестов, если быть точным,

L>> но в данном контексте это неважно). Соответственно, если у тебя 1000 функций,
L>> то тебе понадобится 3000 тестов, по грубой оценке.
М>вы снова соглашаетесь со мной, что исчерпывающий тест намного больше по объему кода и по трудоемкости написания, чем то, что он тестирут. модели для других целей строят.

Цитату можно, где я соглашался?
Эти 3000 тестов будут состоять из трех-четырех строчек каждый; трудоемкость их написания на фоне затрат на разработку основного кода незаметна, а объем — вообще странная метрика. Более того, факт написания тестов оказывает положительный эффект на разработку собственно кода, поскольку тестируемый код должен удовлетворять критериям тестируемости, которые магическим образом совпадают с обобщенными критериями "хорошести" и "поддерживаемости" кода. Выполнение этих тестов занимает несколько секунд.
Трудоемкость такого подхода совершенно ничтожна по сравнению с затратами, которые потребовались бы на орагнизацию аналогичного по покрытию набора функциональных black-box тестов.

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


А вот тут я, как и обещал, порву тебя на лоскуты. Пульт управления микроволновки — это типичный пример state machine. То, что в ней нет тупиков, доказывается в первую очередь диаграммой состояний вашей машины и таблицей переходов. Верифицируется ручками, глазками, и девайсом /dev/brain. Как и все подобные конечные автоматы. А вот после реализации можно и нужно написать функциональный тест, который в том числе проверит, что из каждого меню можно выйти в $HOME.


L>>Дорогой, ты только что привел примеры двух индустрий,

L>>где юнит-тестирование проводится практически везде.
М>и обе индустрии вбухивают в тестирование мегабабло. потому что цена ошибки дороже.

Знаем мы, куда они мегабабло вбухивают. На бонусы непричастным и сетрификацию некомпетентными.

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


L>>Я тебе посоветую не разрабатывать программно-аппаратный комплекс,

L>>так как из твоих слов понятно, что ты в этой теме ни бум-бум.
М>кто-то грозился отобрать отладчик...

... компилятор тоже надо отобрать. А то ногу себе прострелишь.

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

L>> Сейчас ты лезешь в розетку с амперметром.

М>сколько слов, наездов, самоуверенности и при этом никаких возражений по существу. вы говорите, что юнит тесты нужны. ок, допустим это так. осталось только оценить расходы на их разработку и заложить их в бюджет.

Нет никаких особых расходов на разработку этих тестов. Вообще, когда спрашивают о расходах на разработку тестов, это является признаком полного непонимания подхода TDD и использования юнит-тестов в разработке. Этот процесс не разделим на составные части.

Как только разработчик становится адептом церкви TDD на своем опыте узнает преимущество юнит-тестирования, для него юнит-тесты перестают существовать как отдельная сущность. Для нас процесс разработки есть процесс написания собственно кода и кода, его тестирующего. Они неотделимы друг от друга, как неотделимы и наши собственные оценки затрат и как результат, бюджет. Кроме того, наши оценки временных затрат зачастую являются гораздо более точными, так как, прежде чем приступить к estimations, мы должны не только ответить на вопрос "а что мы будем писать", но и "а как мы это будем автоматически тестировать".

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

М>вы так и не ответили на вопрос -- как убедиться в том, что в тесте нет ошибок?


Ошибки в тестах, как правило, ортогональны ошибкам в коде, который они призваны проверять. Опять же, если ошибка в тесте приводит к тому, что тест не проходит, просто вернись и пофикси ее. От ошибок, приводящих к false positive, помогает практика писать negative test cases.
www.blinnov.com
Re[10]: Как важно проверять в программах ошибки до конца
От: b-3 Россия  
Дата: 21.06.12 04:30
Оценка:
Здравствуйте, landerhigh, Вы писали:

L>здесь. Дальше распространяться на эту тему не буду, но даже по-русски будет корректнее спросить "а пишете ли вы вообще тесты", потому что любое прошедшее время подразумевает, что тесты писали,

давно Present Perfect стало прошедшим? Present как переводится?
Забанен с формулировкой "клинический дисидент".
Re[11]: Как важно проверять в программах ошибки до конца
От: landerhigh Пират  
Дата: 21.06.12 04:54
Оценка: -1
Здравствуйте, b-3, Вы писали:

b-3>Здравствуйте, landerhigh, Вы писали:


L>>здесь. Дальше распространяться на эту тему не буду, но даже по-русски будет корректнее спросить "а пишете ли вы вообще тесты", потому что любое прошедшее время подразумевает, что тесты писали,

b-3>давно Present Perfect стало прошедшим? Present как переводится?
Рассказать, как переводится Perfect?

Это время используется для обозначения действия, завершенного к настоящему моменту без указания конкретного периода в прошлом. То есть "have you done any unit testing at all?" == "писали ли вы тесты когда-либо?". Посыл ложный, о чем я и говорю.
www.blinnov.com
Re[5]: Как важно проверять в программах ошибки до конца
От: Deprivator  
Дата: 21.06.12 05:40
Оценка:
Здравствуйте, quwy, Вы писали:

Q>Однажды, очень давно, довелось мне написать это:

Q>Откуда взялся этот код и почему он выглядит именно так, должно быть понятно любому здесь. Расскажите неграмотному дельфисту что-нибудь про формошлепство и непонимание внутреннего устройства компьютера.

кстати да, абсолютно чудовищный код.
In P=NP we trust.
Re[7]: Как важно проверять в программах ошибки до конца
От: Privalov  
Дата: 21.06.12 07:09
Оценка:
Здравствуйте, SingleUseAccount, Вы писали:

SUA>А нечего было так глубоко залазить


Попал мне как-то древний исходник на xBase (не помню, Fox или Clipper). Автор того кода передачу управления вверх организовывал как раз, запихивая определенные участки кода в WHILE и выставляя в условии хитрые комбинации флажков. И столько этих циклов нагородил, что я тогда впервые пожалел, что goto в xBase предназначен для прыжков по записям в таблице, а не по коду программы. Я раньше прочитал пару строк на Фортране 4, так что макаронами меня запутать было сложнее, чем их эмуляцией.
Re[5]: Как важно проверять в программах ошибки до конца
От: AndreyM16  
Дата: 21.06.12 08:04
Оценка: 2 (1)
Здравствуйте, мыщъх, Вы писали:

М>Здравствуйте, landerhigh, Вы писали:


L>>Здравствуйте, newCL, Вы писали:


L>> для кого юнит-тесты эквивалентны занятию ерундой, срочно сменить профессию.

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

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

М>если вы не согласны и уверены в себе и своих знаниях -- плз, напишите функцию факториала вместе с тестом.


Факториал писать не приходилось, но приходилось писать много других алгоритмов из вычислительной математики и computer science. Без юнит тестов там вообще невозможно написать, хоть какой-то более менее сложный алгоритм.
Re[9]: Как важно проверять в программах ошибки до конца
От: Michael7 Россия  
Дата: 21.06.12 08:21
Оценка:
Здравствуйте, Eugeny__, Вы писали:

E__>Здравствуйте, Michael7, Вы писали:



SUA>>>Здравствуйте, linuz, Вы писали:

L>>>> Я видел как goto-ненавистники лепили мега-монстра с кучей хитровложенных ифов, do-while и свитчей только для того чтобы правильно выйти из нескольких циклов. Там без бутылки не поймешь когда и куда оно выходит, лучше бы написали goto.

SUA>>>А нечего было так глубоко залазить


M>>То есть, чтобы не использовать goto теперь надо еще и от вложенных циклов отказаться?


E__>Ну, вообще-то, желательно. Вложенные циклы без вынесения внутреннего в отдельную функцию, весьма трудночитаемы.


Мда, то есть там, где можно было бы написать понятный и обозримый код из десятка строчек с допустим тремя вложенными циклами и элементарными выходами с помощью goto, надо в итоге нагородить или кучи if-ов и флагов для проверки или выносить циклы в отдельные функции, чтобы можно было выходить по exit. А если выходить надо и со второго уровня и с третьего? Отдельные функции и на все это? Хотя exit тоже некошерен

Такая боязнь goto уже на какое-то сектантство в программировании начинает походить.
Re[10]: Как важно проверять в программах ошибки до конца
От: Michael7 Россия  
Дата: 21.06.12 09:09
Оценка:
Здравствуйте, мыщъх, Вы писали:

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


О, кстати, да. Буквально месяц назад пришлось разбираться с подобной хренью. Есть крутая система, которая выдает по запросам к ней данные в XML-формате. Не знаю, что там курили программисты, которые писали выдачу, но в некоторых случаях XML не то, что валидацию на соответствие DTD не проходят, а они и вовсе некорректные как XML из-за того, что во-первых, там банально знаки < > и & (спецсимволы) в данных представлены как есть. На чем падает извлечение данных стандартными средствами. В итоге пришлось извращаться и делать предобработку, заменяя в нужных местах эти знаки. Причем я заведомо не смог это сделать совершенно безглючным, потому что я не написал полностью свой парсер даже не XML, а того псевдоXML, что приходится обрабатывать. Просто на примерно том наборе данных, что выдается, замена происходит корректно. Тьфу-тьфу Во вторых, иногда этот XML и вовсе имеет пересекающиеся теги. Хорошо еще, что все такие случаи пока что строго определенные — иногда корневой элемент почему-то закрывается раньше предыдущего вложенного. Других вариантов еще не встретилось.

При этом такие глюки примерно в одном XML-файле из 5000 и пока тестировали и принимали в эксплуатацию на некотором множестве опытных все работало без сбоев. Все замечательно.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.