четверг, 22 августа 2013 г.

ORACLE. Перенос значений из одной таблицы в другую

Вернемся к нашей задачке, которую я рассматривала ранее.

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

Создаю отдельную табличку для создания нужного количества телефонов. Теперь мне надо данные оттуда перенести в folks, учитывая то, что телефонов нет у 1 человека, 2,3 6, 11 итд. То есть нельзя просто взять и перетащить данные. Надо их распихать в отдельные строки.



Хотя, конечно, один из вариантов решения - создав нужное количесто телефонов отдельно, перенести их как раз скопом, затерев уже существующие.

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

1. Добавляем поле id к телефонам

alter table phone add ( id INTEGER );
commit; 

2. Заполняем новую колонку значениями id тех людей, у которых еще нет телефонов.

insert into phone (id)
(select a.id from
((SELECT  
  rownum AS rw_id, 
  id  
FROM folks WHERE phone_number IS NULL) a
JOIN
  (SELECT rownum AS rw_id  
  FROM phone
  ) b
ON (a.rw_id=b.rw_id)));

commit;

3. Метчим 2 таблицы по id людей!

MERGE INTO folks b USING phone ab ON (b.id = ab.id)
WHEN MATCHED THEN
  UPDATE
  SET b.filed_1    = ab.filed_1,
    b.filed_2      = ab.filed_2,
    b.filed_3      = ab.filed_3,
    b.filed_4      = ab.filed_4,
    b.filed_5      = ab.filed_5,
    b.filed_6      = ab.filed_6,
    b.filed_7      = ab.filed_7,
    b.phone_number = ab.phone_number,
    b.filed_9      = ab.filed_9;
    
commit;

Все Smile :)

ORACLE. Функция TRANSLATE

Конечно же, реальность немного сложнее, чем прогон тестовых данных. Что, кстати, только подтверждает следующие факты:

  • Изначально идея должна проверяться на модульных тестах - небольших объемах данных, очень простых. Потому что, если не работает простенькая функция, но обнаруживаем мы это спустя 3 часа регрессии - это не гуд.
  • После модульных тестов прогоняем интеграционные, потому что, если что-то работает на маленьких тестовых данных, не факт, что будет так же хорошо работать на больших и более-менее реальных объемах.

Итак, настоящая задача - есть у меня табличка с телефонами. Примерно такая

CREATE TABLE phone (
  field_01 NUMBER,
  field_02 DATE,
  field_03 VARCHAR2(50 byte),
  field_04 NUMBER,
  field_05 VARCHAR2(100 byte),
  field_06 VARCHAR2(100 byte),
  field_07 CHAR(100 byte),
  phone_number VARCHAR2(100 byte),
  field_09 VARCHAR2(100 byte)
);


И мне надо 100 телефонов превратить в 200 (реальные данные, конечно, чуть-чуть побольше Smile :) ). Дублирующиеся данные - зло, тестировать лучше на уникальных. Что делать? А почему бы и не прибавить к уже существующим телефонам 100 или 1000?

Сказано, сделано. Проверила сначала сам запрос, как мне строку (varchar2) превратить в число, прибавить к нему что-то и потом сконвертировать обратно. Тест прошел успешно.

Но, когда я этот запрос применила к реальной табличке

INSERT INTO phone (
  field_01,
  field_02,
  field_03,
  field_04,
  field_05,
  field_06,
  field_07,
  phone_number,
  field_09
)
(SELECT
  field_01,
  field_02,
  field_03,
  field_04,
  field_05,
  field_06,
  field_07,
  to_char(to_number(phone_number)+10),
  field_09
from phone);

То словила неприятный эксепшен "Invalid number".
В чем дело? Да в том, что телефоны можно записать по разному:
  • 111-11-11
  • 8 926 11 22 345
  • 8 (926) 111-22-34
  • ...
И вот всякие строки с тире в число уже так просто не переведешь...
Что делать? 

Можно воспользоваться функцией TRANSLATE Функция TRANSLATE анализирует строку str и заменяет в ней все символы, встречающиеся в строке from_mask, на соответствующие символы из to_mask. Для корректной работы функции строки from_mask и to_mask должны иметь одинаковую длину или строка from_mask должна быть длиннее, чем to_mask. Если from_mask длинее, чем to_mask, и в процессе обработки строки str обнаружатся символы, соответствующие одному из символов from_mask, и при этом им не найдется соответствия в to_mask, то такие символы будут удалены из строки str. Если передать from_mask или to_mask, равное NULL, то функция возвратит значение NULL. Сравнение производится с учетом регистра.

Отлично! Накладываем маску "0123456789", все, что ей соответствует, заменим на пробел. 
А потом применим к ней trim - обрезание пробелов в начале и в конце.

И если функция TRANSLATE после обрезания пробелов вернет нам null (то есть в ней больше ничего и не было) - значит, это число! Можно смело добавлять к нему 10, 20 или сколько там нам нужно.

А вот если функция вернет не null, то там не число. И, чтобы не влететь на эксепшен, лучше просто сгенерировать рандомное значение в определенном диапазоне. Так как у меня Мегафон, то и данные я генерю для 926 Smile :)

Получается, нам надо "или или" - в этом нам поможет оператор CASE. Получаем

case when trim(TRANSLATE(to_char(p01_phone_number_txt),'0123456789', ' ')) is null
  then to_char(to_number(phone_number) + 1111)
  else to_char(trunc(dbms_random.value(89261111111,89268888888), 0))
end

Функция trunc(x, 0) делает число x целочисленным, так как dbms_random генерирует дробные значения.

Иииии, запускаем весь запрос

INSERT INTO phone (
  field_01,
  field_02,
  field_03,
  field_04,
  field_05,
  field_06,
  field_07,
  phone_number,
  field_09
)
(SELECT
  field_01,
  field_02,
  field_03,
  field_04,
  field_05,
  field_06,
  field_07,
  case when trim(TRANSLATE(to_char(p01_phone_number_txt),'0123456789', ' ')) is null
  then to_char(to_number(phone_number) + 1111)
  else to_char(trunc(dbms_random.value(89261111111,89268888888), 0))
end,
  field_09
from phone);

И снова получаем  "Invalid number" о_О

Смотрим на данные, применив к ним trim(TRANSLATE(to_char(p01_phone_number_txt),'0123456789', ' '))

Видим, что у нас есть некоторые значения формата "892611 22345". С пробелом посередине. И опять, с пробелом - не число, преобразовывать не буду. А, проходя через функцию, получаются ведь все пробелы, что подпадает под первое условие. Функция считает, что мы получили число и радостно отдает его в then, где не менее радостно падает, так как число с пробелом посередине числом не является.

Что делать? Повсюду баги, блин... 
Приходится изгаляться, чтобы их обойти - в функции then прописываем еще один TRANSLATE, который заменит нам все пробелы на нули.

Ну и заодно обрежем строку, а то получим на выходе больше 11 символов - и опять все упадет...
substr(x,1,11) - берет строку x и, начиная обрезает все после 11 символа (считать начинает с 1).

Получаем case:

case when trim(TRANSLATE(to_char(p01_phone_number_txt),'0123456789', ' ')) is null
  then to_char(to_number(substr(TRANSLATE(trim(p01_phone_number_txt),' ','0'),1,11)) + 1111)
  else to_char(trunc(dbms_random.value(89261111111,89268888888), 0))
end

А полный запрос:

INSERT INTO phone (
  field_01,
  field_02,
  field_03,
  field_04,
  field_05,
  field_06,
  field_07,
  phone_number,
  field_09
)
(SELECT
  field_01,
  field_02,
  field_03,
  field_04,
  field_05,
  field_06,
  field_07,
  case when trim(TRANSLATE(to_char(p01_phone_number_txt),'0123456789', ' ')) is null
  then to_char(to_number(substr(TRANSLATE(trim(p01_phone_number_txt),' ','0'),1,11)) + 1111)
  else to_char(trunc(dbms_random.value(89261111111,89268888888), 0))
end,
  field_09
from phone);

среда, 21 августа 2013 г.

Notepad++, небольшие регэкспы

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



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

Итак, есть схема создания некой таблички

CREATE TABLE test (
  field_01 NUMBER,
  field_02 DATE,
  field_03 VARCHAR2(50 byte),
  field_04 NUMBER,
  field_05 VARCHAR2(100 byte),
  field_06 VARCHAR2(100 byte),
  field_07 CHAR(100 byte),
  field_08 VARCHAR2(100 byte),
  field_09 VARCHAR2(100 byte)
);

Нам надо взять все эти поля и переложить в табличку test_data.
Ищем и заменяем:

Примеры написаны в стиле

  • Find - то, что ищем
  • Replace - то, на что заменяем
Поехали, большинство замен шли в режиме регулярных выражений:
  • VARCHAR2\(.* byte\),
  • ,
Тут важно помнить о том, что скобки надо заэкранировать, иначе результат будет нулевой.

Также убираем CHAR и NUMBER, последнюю строку вручную, ну или убрать потом из find запятую. Дата:
  • \sDATE
  • пусто
Тут, опять же, важно не забыть про "\s", иначе по закону подлости, обязательно найдутся поля вида field_date_2, а оттуда нам вырезать ничего не надо.

Отлично, все вырезали, получили примерно так


SELECT (
  field_01 ,
  field_02 ,
  field_03 ,
  field_04 ,
  field_05 ,
  field_06 ,
  field_07 ,
  field_08 ,
  field_09  
)...;


А теперь мы хотим сметчить эти поля в test_data и test. И получить что-то типа


WHEN MATCHED THEN
  UPDATE
  SET b.field = ab.field

Только для всех полей. Ок, сначала удаляем все пробелы
  • \s
  • пусто
Потом пишем
  • (.*),
  • b.\1 = ab.\1,
Тут, опять же, важно помнить, что в поле replace мы для подстановки группы из регулярного выражения должны писать "\", а не "$".

Ну и наконец, простейший пример Smile :)

Нам надо взять названия наших филдов

  field_01 ,
  field_02 ,
  field_03 ,
  field_04 ,
  field_05 ,
  field_06 ,
  field_07 ,
  field_08 ,
  field_09

И переложить в одну строку, чтобы потом добавить в файл с тестовыми данными. Казалось бы, элементарно
  • $
  • пусто
Но тут возникает проблема - блокнот находит конец строки, и даже типа делает замену, только внешний вид текста не меняется. Что делать? Переключаем на расширенный режим (Extended) и вводим
  •  \r\n
  • пусто
Такие вот небольшие примеры из жизни тестировщика, подготавливающего тестовые данные Smile :)

вторник, 20 августа 2013 г.

ORACLE. Размножение чисел добавлением к ним 10

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

Итак - у нас есть табличка, в ней числовые данные, но тип у них VARCHAR2.
Надо их переложить в другую таблицу, а потом еще раз переложить, но добавив к значениям 10 (20, 30 - не важно), чтобы не дублировать значения.



Проверяем на маленьком объеме (модульное тестирование).

Создаем таблички

create table test (id number, data VARCHAR2(60 byte));
create table test_data (id number, data VARCHAR2(60 byte));

insert into test values (1, 1);
insert into test values (2, 2);
insert into test values (3, 3);
commit;

Проверяем, что получилось:

select * from test;
select * from test_data;

Заполняем таблицу test_data значениями таблицы test

insert into test_data (data) 
select data from test;
commit;

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

insert into test_data (data) 
(select to_char(to_number(data)+10) from test);

commit;

Вот и все Smile :)

вторник, 13 августа 2013 г.

Светлана Иванова. Мотивация на 100%



Ссылка на книгу (издательство "Альпина Паблишер")

Прочитала книжку по рекомендации Натальи Руколь. Очень любопытная!

Написана довольно простым языком, интересная. А главное - в конце каждой главы идет задание для самостоятельной работы. Это самый эффективный тип книжек, книга-тренинг. Тут главное - не лениться и выполнять задания.

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

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

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

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

Кстати, у меня пока не получается посидеть и помедитировать над данным упражнением, но я придумала скрестить его с книжкой "Сначала нарушьте все правила" и поискать таланты, начав с себя. Так что начало положено! Посмотрим, что мне это все принесет, но я вас уверяю - это как минимум интересный опыт. Всем рекомендую Smile :)

PS - Добавила книгу в общий список прочитанных мною книг.

воскресенье, 11 августа 2013 г.

Как применять свои таланты в тестировании?

Читаю сейчас книжку "Сначала нарушьте все правила", интересные вещи узнаю, о себе в частности.

Например, вы знаете, что талант - это возобновляемая модель мышления, чувств или действий, которая может продуктивно использоваться?

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

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

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

Это все хорошо, но как быть с работой? Я вот, почитав книжку, внезапно задумалась и поняла, что я пытаюсь это и в работе внедрить. Например, есть принцип "5 почему?", о котором очень здорово рассказала Наташа Руколь на конференции SQA Days 10. Но у меня не получается просто сидеть и медитировать - ага, вот бага нашлась, а почему она нашлась сейчас? Почему мы пропустили ее раньше? Врядли я к чему-нибудь приду, таким образом размышляя. Нет, бывает. конечно, но редко.

Тогда я поступила иначе - найденные проблемы я стала выписывать. Придумала для себя шаблон с заголовками "Когда нашлась? Где? Какие меры были приняты для устранения?" и пошла его заполнять. Конечно, что-то получилось дублирование информации, потому что достаточно было скопипастить из джиры комментарий к задаче. Но где-то я с удивлением обнаружила возможности улучшения. Они не были приняты раньше, так как тогда это было и не нужно. Но теперь, обладая новой информацией, я поняла, что надо принимать меры.

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

пятница, 9 августа 2013 г.

Ох уж мне эта карма тестировщика!

Недавно пошла к банкомату, зарплату снимать.


Все бы хорошо, если бы не карма Smile :)

Так, вводим пин-код, выбираем сумму для снятия. Банкомат начинает издавать звуки пересчитывания купюр, и тут... Экран банкомата начинает мигать!!!

Ощущения, я вам скажу, те еще! Smile :)
Ведь ладно бы, сломалось что-то при вводе пин-кода или пока по менюшке лазаешь. Но когда тебе уже выдаются деньги? А вот спишут их с тебя, а деньги не дадут. И ходи потом, доказывай, что банкомат сломался...

На мое счастье, после нескольких миганий там таки отрисовались часики "подождите, банкомат думает". Но, как пользователь, честно вам скажу - эту отрисовку надо тестировать тщательно! А то ведь до инфаркта можно довести особо впечатлительных )))

четверг, 8 августа 2013 г.

При оформлении бага критикуйте проблему, не людей!

Как оформлять баг-репорт?

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

Представьте себе, открываете Вы сайт, который Вам срочно срочно нужен для покупки очень важной вещи, например. Выбираете все, проходите все шаги и тут... Ошибка! Причем неизвестная. И давай по новой. Заполняя повторно все данные, тяжело оставаться равнодушным.

А теперь представьте себе, что Вы - тестировщик. И примерно такая же ошибка обломала Вам тестирование. А все ведь работало, но разработчик решил куда-то в соседний модуль "бантик" прикрутить, небольшой... А поломалась важная функциональность.

Эмоциональные ребята сразу поднимут крик "Ай-яй-яй! Ты что! Так нельзя, посмотри, какую багу ты тут сделал!! Позор тебе и порицание!"


Но, ребята - так ведь тоже нельзя.
Надо просто приложить ситуацию к себе - что будет, если к тебе придет друг \ сосед \ коллега и начнет в чем-то обвинять? Да даже если ты правда виноват, первая реакция на нападение - это защита. Хочется оправдаться, рассказать, почему именно так, а не иначе. Или вообще сказать, что "я не я, корова не моя".

А если коллега настаивает? Внутри появляется явное неодобрение этого самого коллеги. И работать бок о бок будет уже тяжело. У Вас остается в голове некий эмоциональный "якорь" - ага, вон Петя, он только ломать и может, а сейчас еще и оправдываться начнет, фи.

И у Пети будет такой же негативный якорь - О боже, опять этот Вася со своими претензиями. Иди попробуй лучше код написать, тут же не все так просто. Но разве этот будет слушать? Только обвинять и горазд...

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

Есть отличное правило - когда оформляете баг-репорт, забудьте про эмоции. Никогда, никогда не обвиняйте ни в чем людей. Критикуйте не работу коллеги (ты сделал ошибку!), а саму проблему (у нас тут есть проблема).

Поверьте, от этого всем только лучше станет.

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

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

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

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

А здесь разве тот случай? Ой сильно врядли... Интересной была реакция на feedback от группы разработки ("так и задумано"):

Кем задумано-то? Если те, кто задумывал, русского не знают, это не значит, что так и надо делать. Кому-то и мат в разговоре норма, значит, теперь все будем на мат переходить?

Читая такой комментарий, поневоле поражаешься, он настолько странно звучит!
Я уверена, что и сам автор комментария, увидя его спустя время, поймет, о чем идет речь.

Нельзя быть эмоциональным, когда пишешь комментарий к баге.
Это сложно осознать, когда ты увидел проблему, а тебе ее еще и завернули со статусом Won`t fix, хотя ты то уверен, что это ошибка, причем серьезная ошибка!!!

Конечно, хочется рвать и метать, бежать доказывать коллегам свою точку зрения. Ну так и бегите! Коллеги не звери, они все поймут Smile :)

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

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

И вот представьте, открываешь ты задачу в баг-трекере, читаешь комментарии, чтобы понять, что там неправильно было и видишь эмоциональный комментарий в духе "Да как так можно!!! Кошмар и ужас!". И это кажется таким неестественным. Ведь это тогда ты был на эмоциях и так и писал. А сейчас уже столько времени прошло и тебе нужна именно информация, никак не эмоции.

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

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

Так что позитив оставляем (но редко!! Баг-трекер не чатик, флудить постоянно там нельзя), негатив убираем. И все будут довольны, и отношения хорошие!

PS - комментарий студента приведен с согласия автора

 

воскресенье, 4 августа 2013 г.

TEST IT. Как же стать тестировщиком, с чего начать и где учиться?

Коллеги, всем привет!! На связи TEST IT! Smile :)


И сегодня с Вами снова я, сменная ведущая Киселева Ольга.

Сегодня мы с вами снова вернемся к теме "А как вообще стать тестировщиком?" и ответим на вопрос Татьяны:

Здравствуйте!

    Меня зовут Татьяна, совсем недавно я заинтересовалась тестированием. Читаю тематическую и околотематическую литературу, форумы, блоги;), подписки. Информации просто море, и, знаете, я начала понимать, что ещё немного, и -- утону.

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

    Итак, вот, что меня интересует:

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