пятница, 15 июля 2011 г. - www.msmirnov.ru

Китайский код

Не смог удержаться, чтобы не запостить небольшой образчик китайского кода, который попался на глаза мне на днях.
Это не прикол – это реальный кусочек кода приложения.


            string s = Request.QueryString["action"];
            // s may have "restore" or "remove" values

            switch (s[2])
            {
                case 's':
                case 'S':
                    ..............
                    break;

                case 'm':
                case 'M':
                    ..............
                    break;

            }


Как говорится, это было бы смешно, если бы не было так грустно……
Мой сайт - www.msmirnov.ru

воскресенье, 26 июня 2011 г. - www.msmirnov.ru

Летний Аналитический Фестиваль-2011 (ЛАФ-2011)

Вчера я посетил наверное уже ставший традиционным Летний Аналитический Фестиваль-2011 (ЛАФ-2011), который как и в прошлом году проходил в Иваново и был посвящен системному анализу.

О ЛАФ-2010 я писал здесь и здесь.


Было приятно увидеть множество знакомых лиц с прошлого фестиваля.

Как и в прошлый раз фестиваль прошел в теплой непринужденной, я бы даже сказал дружеской, и вместе с тем, профессиональной обстановке.

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


Лично для себя я отметил следующие доклады:


1. Ирина Левенец "Управление ожиданиями в продуктовой разработке". На мой взгляд интереснейший доклад.

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

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

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

Соответственно, ценность сервиса для заказчика снижается.

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

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

- Поскольку ресурсы по разработке обычно ограничены, а множество клиентов генерирует поток запросов на изменение, необходимо выполнять сортировку новых требований.
Здесь Ирина привела интересный термин "Triage".

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

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

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

- Вовлекать заказчиков в процесс сортировки требований. Это способствует повышению адекватности заказчиков.


2. Сергей Мартыненко "Варианты управления требованиями". Как и в прошлом году, у Сергей был очень интересный доклад.

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

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

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

- Хороший способ распределения требований по релизам:

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


3. Денис Казика. "Внедрение ITIL/ITSM" Тоже довольно интересный доклад.

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

Для решения проблем были предприняты следующие шаги:

- Была внедрена система управления инцидентами (нечто типа внутренней системы баг-трекинга.) Все запросы в IT-подразделение могли теперь поступать только через нее (до внедрения этой системы ситуация была примерно такая, как говорил Сергей Мартыненко - кто громче кричит или у кого больше зарплата, того требования и реализуются быстрее). Для того, чтобы отучить сотрудников от старых привычек работы с IT-отделом, двери отдела даже пришлось запирать на две недели, чтобы никто из других отделов не мог попасть внутрь не соблюдая регламент.

- Были внедрены внутренние регламенты работы IT-подразделения.

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

- Была введена должность бизнес-аналитика.

Весь процесс занял примерно 2.5 года.


После всех преобразований:
- IT-подразделение стало бизнес-образующим.

- Исчезли конфликты между IT-подразделением и другими подразделенями.

- Бизнес компании стал более эффективным.


4. Алексей Киселев "Могут ли быть выгодны ошибки аналитика или история одного тендера".

Алексей рассказал о сложностях работы с государственными заказчиками и участия в государственных тендерах.

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

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

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

- Гос.заказчики не признают итеративную разработку. Только водопад.


Пожалуй, это были самые интересные для меня доклады.


К сожалению мне не удалось попасть на мастер класс Дмитрия Безуглова, но я надеюсь увидеть его как-нибудь позже.

Кроме того, не удалось побывать на интересном мастер-классе Ирины Векленко "Анализируй это: Жизнь как Проект", но я также надеюсь пообщаться с ней позже.

Еще хотелось бы отметить, что несколько раз в перерывах между докладами, аналитик Павел Сафин радовал всех собравшихся виртуозной игрой на рояле, за что ему отдельное большое спасибо!


Я надеюсь, что в следующем году состоится ЛАФ-2012 и буду очень рад присутствовать на нем.

Хотелось бы поблагодарить всех организаторов и участников фестиваля за то, что они делают!


All you need is... ЛАФ!
Мой сайт - www.msmirnov.ru

среда, 22 июня 2011 г. - www.msmirnov.ru

Сложности распределенных команд и проектов

В данном сообщении я решил описать сложности, которые возникают в процессе работы над большими проектами в составе распределенных команд.

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

Еще хочу обратить внимание, что данные проблемы не являются не решаемыми.

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


1. Часовые пояса.
Большая разница во времени (например, 12 часов) существенно замедляет процесс разработки.

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

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

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

Можно, конечно, не задерживаться, а просто написать письмо, но это еще хуже.

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


2. Языковой барьер.
Де-факто инструментом общения сейчас является английский язык.

Писать и читать на нем все более или менее уже научились.

Намного сложнее слушать и быстро отвечать.

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

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

Ну и совсем плохо, когда все они с сильным акцентом быстро и одновременно говорят по conference-связи с плохим качеством, при котором часть звуков и слов просто пропадает.  



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



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


5. Демотивация.
Предыдущий пункт приводит к демотивации членов команд, так как они не чувствуют глубокой причастности к работе над проектом. Проект на становиться для них, что называется “своим”.

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


Зачастую бывает проще не задавать вопросов, нежели пытаться чего-то добиться. 


6. Сложности в соблюдении единого стиля разработки.
Это касается как стандартов кодирования, так и технических и архитектурных решений.


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



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


8. Важные вопросы могут решаться не по принципу выбора верного решения из нескольких возможных, а по принципу близости протеже решений к руководству. Последствия, я думаю, очевидны.
Мой сайт - www.msmirnov.ru

понедельник, 20 июня 2011 г. - www.msmirnov.ru

Поздравляю Андрея Маркеева!

Хочу поздравить Андрея Маркеева с отличным выступлением на Sharepoint User Group!

Всегда приятно видеть, как человек своими личными усилиями достигает новых планок в своей профессии.
Мой сайт - www.msmirnov.ru

понедельник, 30 мая 2011 г. - www.msmirnov.ru

Создание тестов для Selenium на C# для web-приложений на ASP.NET


Как я и обещал ранее здесь, привожу пример разработки тестовых сценариев для автоматизированного тестирования web-приложений на C# с использованием библиотеки Selenium 2.0b3.

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

Далее по шагам рассмотрим пример создания тестового сценария проверки логина на тестируемый сайт.
  1. В Visual Studio.NET cоздаем новый проект – библиотеку классов на C#.
    В данную библиотеку помещаем ссылки на библиотеки Selenium:
    • Selenium.WebDriverBackedSelenium
    • WebDriver.Common
    • WebDriver.Remote
    • WebDriver.Remote.Common
    • WebDriver.Firefox
    • WebDriver.IE

    Все эти библиотеки доступны для загрузки с сайта http://seleniumhq.org/download – Скачать необходимо Selenium WebDriver версии 2.0b3 – речь в статье пойдет о ней.

  2. Создаем класс TestFramework который будет предоставлять нам основные функции по выполнению скриптов.

       1:  public class TestFramework
       2:      {
       3:          static RemoteWebDriver _WebDriver;
       4:   
       5:          public static RemoteWebDriver WebDriver
       6:          {
       7:              get
       8:              {
       9:                  if (_WebDriver == null)
      10:                      _WebDriver = new FirefoxDriver();
      11:   
      12:                  return _WebDriver;
      13:              }
      14:          }
      15:   
      16:          public static void OpenURL (string URL)
      17:          {
      18:              WebDriver.Navigate().GoToUrl(URL);
      19:          }
      20:   
      21:          public static IWebElement FindWebElement(WebItem webItem)
      22:          {
      23:              if (webItem.ID != "")
      24:                  return WebDriver.FindElementById(webItem.ID);
      25:   
      26:              if (webItem.ClassName != "")
      27:                  return WebDriver.FindElementByClassName(webItem.ID);
      28:   
      29:              if (webItem.XPathQuery != "")
      30:                  return WebDriver.FindElementByXPath(webItem.ID);
      31:   
      32:              return null;
      33:          }
      34:   
      35:          public static void Delay(int Seconds = 10)
      36:          {
      37:              System.Threading.Thread.Sleep(Seconds * 1000);
      38:          }
      39:      }


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

    При этом, экземпляр класса RemoteWebDriver содержит ссылку на объект драйвера, реализующего работу с конкретным браузером – IE, FireFox, Chrome.

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

    Метод OpenURL,как видно из названия предназначен для открытия различного рода ссылок.

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

    Данный метод возвращает экземпляр интерфейса IWebElement, который реализуется всеми страничными элементами Selenium.

    Метод использует возможности поиска объектов на странице по их ID, имени css-класса или запросу XPath. Вообще говоря, Selenium предоставляет больше возможностей поиска, но в данном примере я оставил только эти три, как наиболее часто применяемые.

    Последний метод Delay предназначен для приостановки тестов до момент окончания загрузки страниц.


  3. Создаем класс WebItem, который я упоминал выше.

       1:  public class WebItem
       2:      {
       3:          public string ID;
       4:          public string ClassName;
       5:          public string XPathQuery;
       6:   
       7:          public WebItem(string ID, string ClassName, string XPathQuery)
       8:          {
       9:              this.ID = ID;
      10:              this.ClassName = ClassName;
      11:              this.XPathQuery = XPathQuery;
      12:          }
      13:   
      14:          public void Click()
      15:          {
      16:              TestFramework.FindWebElement(this).Click();
      17:          }
      18:   
      19:          public void SetValue(string Value)
      20:          {
      21:              TestFramework.FindWebElement(this).SendKeys(Value);
      22:          }
      23:      }


    Как видим, это наш собственный класс, который предназначен для работы с элементами на веб-страницах.

    Класс содержит описание способа поиска нашего элемента, а также предоставляет нам возможность задать значение элемента и выполнить нажатие на элемент.


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

       1:  public static class LoginWebItems
       2:      {
       3:          public static WebItem LoginLink
       4:          {
       5:              get
       6:              {
       7:                  return new WebItem("ctl00_Header1_TopHeader1_ExitLinkButton", "", "");
       8:              }
       9:          }
      10:   
      11:          public static WebItem UserNameTextBox
      12:          {
      13:              get
      14:              {
      15:                  return new WebItem("ctl00_ContentPlaceHolder1_EMailTextBox", "", "");
      16:              }
      17:          }
      18:   
      19:          public static WebItem PasswordTextBox
      20:          {
      21:              get
      22:              {
      23:                  return new WebItem("ctl00_ContentPlaceHolder1_PasswordTextBox", "", "");
      24:              }
      25:          }
      26:   
      27:          public static WebItem LoginButton
      28:          {
      29:              get
      30:              {
      31:                  return new WebItem("ctl00_ContentPlaceHolder1_LoginButton", "", "");
      32:              }
      33:          }
      34:      }


    Как видим, класс содержит ссылки на следующие элементы – ссылку на страницу логина, текстовые поля для имени пользователя и пароля, а также непосредственно кнопку логина.


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

       1:  public class PagesActions
       2:      {
       3:          public static void OpenHomePage()
       4:          {
       5:              TestFramework.OpenURL("http://www.test.com/");
       6:          }
       7:      }



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

    Впоследствии это действие может быть использовано во многих тест-кейсах.

       1:  public class LoginAction
       2:      {
       3:          public static void DoLogin()
       4:          {
       5:              LoginWebItems.LoginLink.Click();
       6:   
       7:              LoginWebItems.UserNameTextBox.SetValue("test login");
       8:              LoginWebItems.PasswordTextBox.SetValue("test password");
       9:   
      10:              LoginWebItems.LoginButton.Click();
      11:   
      12:              TestFramework.Delay();
      13:          }
      14:      }


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


  7. Ну и наконец мы создаем класс тест-кейса LoginTestCase, который реализует непосредственно тестирование входа на сайт

       1:  public class LoginTestCase
       2:      {
       3:          public static void DoTestCase()
       4:          {
       5:              PagesActions.OpenHomePage();
       6:   
       7:              LoginAction.DoLogin();
       8:          }
       9:      }


Таким образом, расширяя впоследствии наши классы, мы можем описывать новые элементы страниц и сами страницы.


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


Затем, мы можем использовать наши сценарии в рамках или встроенного unit-тестирования или для тестирования посредством собственного приложения.


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


Мы можем также организовать автоматическое создание багов в TFS – о том, как это сделать я писал в посте “Как создать work item в TFS (Team Foundation Server) из письма в Outlook

P.S.
Другие мои посты на тему Selenium:
1. От QTP к Selenium
2. Создание тестов для Selenium на C# для web-приложений на ASP.NET
Мой сайт - www.msmirnov.ru

понедельник, 23 мая 2011 г. - www.msmirnov.ru

От QTP к Selenium

Последние несколько лет мы использовали Mercury Quick Test Pro (QTP) для выполнения скриптов автоматизированного тестирования наших web-приложений.

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


Для нас Selenium имеет целый ряд преимуществ по сравнению с QTP:

1. Selenium бесплатный. QTP стоит очень дорого.

2. Selenium позволяет разрабатывать скрипты на том же языке программирования, на котором ведется основная разработка – C#, Java и пр. Это избавляет от необходимости изучать еще один язык программирования для разработки тестовых сценариев. Благодаря этому, разработчики могут при случае легко вносить изменения в тестовые сценарии, а тестировщики избавлены от необходимости переучиваться, при переходе в разработчики.

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

4. Тестовые скрипты Selenium можно включать в наборы unit-тестов тестируемого приложения.

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


Есть, конечно, и некоторые сложности во внедрении Selenium (куда же без них?):

1. Очень бедная документация.

2. Более высокие требования к опыту тестировщиков в плане умений программировать.

3. Полное отсутствие инструментария разработки.

4. Отсутствие возможности тестировать Windows-приложения.

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

P.S.
Другие мои посты на тему Selenium:
1. От QTP к Selenium
2. Создание тестов для Selenium на C# для web-приложений на ASP.NET
Мой сайт - www.msmirnov.ru

вторник, 10 мая 2011 г. - www.msmirnov.ru

Заметка о мотивации

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

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

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

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

И сегодня один мой коллега, имени которого я не называю, рассказал мне о той системе мотивации, которая принята в их ИТ-подразделении.


Суть системы такова: зарплата программистов складывается из двух часть: оклад + премия (50% от оклада).

Для каждой задачи ставится срок ее сдачи. Если программист не сдает задачу во время, то от премии всего ИТ-отдела, во главе с начальником, вычитается 1% за каждый день просрочки.

Если после сдачи задачи в ней будут найдены баги, то аналогично: минус 1% за каждый баг со всего ИТ-отдела.

Как говорит коллега, такого, чтобы отдел получил 100% премии, не было еще ни разу.

Интересная система мотивации, не находите?
Мой сайт - www.msmirnov.ru