.Взаимодействие NET.

Начало работы с IronRuby и Rspec. Часть 1

Бен Хол (Ben Hall)

Данная статья основана на предварительной версии IronRuby. Любые содержащиеся в ней сведения могут быть изменены.

В данной статье рассматриваются следующие вопросы.

  • Ruby и типизация по признакам
  • Ruby и Microsoft .NET Framework
  • Использование IronRuby и RSpec
В данной статье используются следующие технологии:
IronRuby

Загружаемый файл с кодом доступен в коллекции кода MSDN
Обзор кода в интерактивном режиме

Содержание

Определение требований и примеров в коде
Ruby и типизация по признакам
Ruby и метапрограммирование
Ruby и .NET Framework
Ruby и CLR
IronRuby изнутри
Тестирование приложения C# с помощью IronRuby
Продвигаясь вперед

«Это не то, что мы просили!» Я уверен, что большинство разработчиков слышали этот возглас клиента вскоре после доставки последней сборки. У клиента могло быть множество причин кричать на бедного разработчика — возможно, были неправильно поняты требования, или часть системы попросту не работает.

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

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

В данной статье я познакомлю вас с Ruby и IronRuby и продемонстрирую некоторые принципы взаимодействия Ruby с кодом, созданным на базе Microsoft .NET Framework. Кроме этого, будет обсуждаться способ использования таких платформ как RSpec для генерации примеров, демонстрирующих задуманное поведение объектов, с предоставлением документации и возможности проверки того, что система правильно сконструирована. Так будет подготовлена база для будущей статьи, в которой будет подробно обсуждаться приемочное тестирование, а также будет показано создание приемочных тестов с помощью IronRuby.

Определение требований и примеров в коде

Для облегчения задачи написания примеров и определения требований необходима некоторая платформа. Существует много различных подходов к написанию автоматизированных приемочных тестов или исполняемых спецификаций. Кто-то успешно использует стандартные инфраструктуры xUnit, другие используют платформы Fit и Fitness. Я нахожу оптимальным подход с использованием разработки на основе поведения (BDD). Дэн Нот (Dan North) создал платформу BDD под названием JBehave, которая позволяет так задавать варианты моделирования, описывающие поведение приложения, что появляется возможность взаимодействовать со всей рабочей группой независимо от технических навыков.

JBehave появился в результате осложнений, с которыми столкнулся Нот при использовании разработки на основе тестирования (TDD), и был реализован для языка Java. Впоследствии Нот создал RBehave, который с тех пор является неотъемлемой частью RSpec, распространенной платформы для Ruby. В RSpec уживаются два разных подхода к BDD: подход Дэна Нота, основанный на примерах и ситуациях, используемых для описания поведения приложения, и подход Дейва Астела (Dave Astel), в котором большее внимание уделяется созданию примеров на объектном уровне.

Для C# существует несколько платформ BDD, например NSpec и NBehave. Основная проблема при написании тестов на C# заключается в том, что истинное назначение теста зачастую скрыто присутствием избыточных структурных элементов и метаданных, таких как фигурные скобки и ключевые слова «public» и «private». В целом, я не думаю, что возможности, предлагаемые посредством C# и NSpec/NBehave, могут соответствовать тому, что доступно благодаря IronRuby и RSpec. Раньше это стало бы главной проблемой разработчиков C#, поскольку было бы невозможно использовать платформу RSpec, основанную на Ruby, для тестирования приложений C#. Теперь, когда есть IronRuby, это больше не является проблемой.

Еще на ранней стадии разработки IronRuby использует преимущества среды выполнения динамического языка (DLR) для создания реализации языка Ruby на основе среды CLR. Имея IronRuby, можно использовать существующие приложения и платформы Ruby совместно с языками, поддерживающими .NET Framework и .NET. В итоге у вас появляется возможность использовать язык Ruby и RSpec для тестирования приложений C#!

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

File.readlines('AboutMicrosoft.txt').map {|line| puts line}

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

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

Ruby и типизация по признакам

Одной из причин, по которой язык Ruby и динамические языки проще читать, является способ, которым они управляют типизацией. Вместо того чтобы тип определялся разработчиком, тип переменной выводится Ruby во время интерпретации кода. Язык остается строго типизированным, но тип переменной определяется динамически.

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

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

   def SayHello(val)
     puts "Hello #{val}"
   end

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

   SayHello("Test") => "Hello Test"
   SayHello(5) => "Hello 5"

Этот метод можно было бы вызвать без использования скобок, поскольку они не являются обязательными в Ruby, и синтаксис стал бы более удобным для чтения.

   SayHello "Test" => "Hello Test"

В C# этого можно достичь с помощью объекта, но давайте посмотрим, как это работает в случае более сложных объектов. Я определил новый метод для вывода результата вызова GetName. До тех пор, пока значение параметра n реализует метод с именем GetName, код будет работать.

def outputName(n)
  puts n.GetName()
end 

Ниже представлены два несвязанных класса.

class Person
  attr_accessor :name
  def GetName()
    @name
  end
end
class Product
  def GetName()
    "The product with no name"
  end
end

У класса Person имеется метод доступа, позволяющий устанавливать имя переменной, а класс Product возвращает значение, указанное прямо в коде. В Ruby нет необходимости писать оператор возврата, последний результат последней строки кода метода возвращается по умолчанию.

При вызове метода outputName вызывается метод GetName, демонстрирующий, как типизация Ruby может расширить возможности многократного использования кода вследствие того, что мы не привязаны ни к одному типу.

outputName(Product.new) => "The product with no name"
$x = Person.new
$x.name = "Ben Hall"
outputName($x) => "Ben Hall"

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

outputName("MyName") => :1:in 'outputName': \
  undefined method 'GetName' \
  for MyName:String (NoMethodError)

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

Ruby и метапрограммирование

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

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

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

class Integer
   def even?()
       self.abs % 2 == 0
   end
end
puts 2.even? => true
puts 1.even? => false

Ruby и .NET Framework

Вместо старого спора о том, какой следует использовать язык — статический или динамический, IronRuby позволяет использовать тот язык, который лучше подходит для вашей работы. Если разумнее использовать C#, вы можете использовать C#. Если требуется более динамический подход, вы можете без труда прибегнуть к IronRuby, используя преимущества его способности взаимодействовать с .NET и динамическую природу языка Ruby. Я предвижу, что будет использоваться смесь разных языков и технологий, например C# — для главного приложения и Ruby — для тестирования.

Среда DLR предоставляет базу для осуществления взаимодействия с .NET. В этих условиях вы сможете при написании кода приложения на языке Ruby использовать преимущества технологии таких пользовательских интерфейсов, как Windows Forms, Windows Presentation Foundation (WPF) и Silverlight.

В IronRuby воспользоваться преимуществами WPF не сложно. Во время выполнения следующего кода вы можете работать с полноценно функционирующим окном WPF, созданным из IronRuby. Вам по-прежнему, как это делалось в случае C#, необходимо с помощью операторов require сослаться на mscorlib и две сборки WPF, поставляемые вместе с .NET Framework 3.0.

require 'mscorlib'
require 'PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
require 'PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'

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

Window = System::Windows::Window
Application = System::Windows::Application
Button = System::Windows::Controls::Button

Затем создайте окно WPF и дайте ему название.

win = Window.new
win.title = 'IronRuby and WPF Interop'

Таким же способом создайте кнопку.

mainButton = Button.new
mainButton.content = 'I'm a WPF button — press me'

В обоих примерах для доступа к полному имени объекта используется псевдоним. Мне требуется, чтобы при нажатии кнопки пользователю отображалось окно MessageBox. Как в C#, можно подписаться на это событие и предоставить блок, вызываемый в момент активирования события нажатия кнопки.

mainButton.click do |sender, args|
  System::Windows::MessageBox.Show("Created using IronRuby!")
end

Наконец, установите в качестве содержимого окна кнопку, создайте новый объект Application и откройте окно.

win.content = mainButton
my_app = Application.new
my_app.run win

fig01.gif

Рис. 1 Использование IronRuby для создания приложения WPF

В этот момент, как показано на рис. 1, отображается в полной мере интерактивное окно WPF, к которому должным образом привязано событие нажатия кнопки. Я работал с .NET Framework точно так же, как я работал бы с библиотеками Ruby. Один из базовых принципов, установленных Джоном Лэмом (John Lam) и его группой, состоит в том, что нужно сохранять верность языку Ruby. Важно, чтобы этот принцип усвоили разработчики, работающие с Ruby в настоящее время, которые не хотели бы менять свой подход к созданию приложений Ruby только потому, что они переходят на IronRuby. Взамен они смогут получать доступ ко всему богатству кода .NET таким же способом.

Ruby и CLR

Еще один пример. Если вы пытаетесь получить доступ к AddRange из IEnumerable, в C# код будет выглядеть следующим образом.

ArrayList list = new ArrayList();
list.AddRange(new [] { 1,2,3,4 });

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

Вместо этого IronRuby для объектов среды CLR переводит вызовы методов Ruby в имя эквивалентного метода среды CLR.

   $list = ArrayList.new
   $list.add_range([1,2,3,4])

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

$list.AddRange([1,2,3,4])

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

Как я упоминал, Ruby выводит тип объектов на этапе выполнения, и точно так же поступает при обработке объектов C#. Рассмотрим ряд методов C#, возвращающих объекты разных типов. Хотя возвращается один и тот же объект, сигнатура метода возвращает либо интерфейс, либо конкретный тип. В рамках моего примера интерфейс определяет единственный метод HelloWorld.

public interface IHello {
  string HelloWorld();    
}

Я создал класс Hello4Times, являющийся наследником Hello3Times, который является наследником интерфейса, но реализовал три дополнительных метода HelloWorld. В рамках класса я определяю новый метод с именем HelloMethodOn4Times, который вызывает базовую реализацию.

public class Hello4Times : Hello3Times {
  public string HelloMethodOn4Times () {
    return base.HelloWorld();
  }
}

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

public static class HelloWorld {
  public static IHello ReturnHello4TimesAsInterface() {
    return new Hello4Times();
  }

В моем коде Ruby имеется два вызова метода. Первый вызов выполняется в методе, определенном интерфейсом, который, как можно было бы рассчитывать, будет работать без осложнений. Но второй вызов обращен к методу конкретного класса. IronRuby определил тип возвращаемого объекта и может обработать эти вызовы методов.

puts InteropSample::HelloWorld.ReturnHello4TimesAsInterface.HelloWorld
puts interopSample::HelloWorld.ReturnHello4TimesAsInterface.HelloMethodOn4Times

Все это происходит, не требуя от вас никакого участия в приведении объекта к конкретному типу для вызова метода.

Развивая эту тему, вы можете расширять объекты .NET точно таким же способом, как объекты Ruby. Отображая окно MessageBox, я не собираюсь определять, какие значки и кнопки следует использовать. Вместо этого мне требуется просто предоставить сообщение.

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

class System::Windows::MessageBox
  def self.ShowMessage(msg)
    System::Windows::MessageBox.Show(msg, msg, \
      System::Windows::MessageBoxButton.OK, \
      System::Windows::MessageBoxImage.Stop)
  end
end

После выполнения следующего блока кода

System::Windows::MessageBox.ShowMessage( \
  "I'm going to show you a message") 

вы можете вызывать метод ShowMessage, результатом будет диалоговое окно с сообщением, показанное на рис. 2.

fig02.gif

Рис. 2 Отображение пользовательского окна MessageBox из Ruby

IronRuby изнутри

Почему возможно взаимодействие? Ответ заключен в DLR. На высоком уровне, когда вы выполняете код Ruby с помощью IronRuby, значительная часть работы выполняется скрытым образом. Во-первых, код, который вы пишите, разбивается и анализируется модулем IronRuby. Затем проанализированный код преобразуется в дерево абстрактного синтаксиса DLR (Abstract Syntax Tree — AST). Это стандартизованное дерево AST, которое все реализации языка, например IronPython, обязаны предоставлять среде DLR для выполнения кода.

DLR, получив AST, преобразует дерево в промежуточный язык (Intermediate Language — IL). Весь код .NET переводится в IL для предоставления среде CLR обобщенного языка. Так IronRuby взаимодействует с .NET Framework — скрытым образом, и весь код выполняется в виде инструкций IL. После того, как DLR выполнит преобразование, IL передается среде CLR для выполнения, и результат возвращается IronRuby.

В ходе этого процесса предпринимаются дополнительные действия для повышения производительности и надежности, например, кэширование. Более глубокие объяснения рекомендую прочитать в рубрике «CLR вдоль и поперек» статью Билла Чайльза (Bill Chiles) «IronPython and the Dynamic Language Runtime» (IronPython и среда выполнения динамического языка) из октябрьского выпуска журнала MSDN Magazine за 2007 г.

В отдельной сборке имеется размещающий интерфейс API, который дает возможность встраивать IronRuby в ваши собственные приложения, что позволяет вам выполнять код Ruby из C# или выполнять пользователям их собственный код.

Более подробные сведения о реализации IronRuby можно получить, загрузив весь исходный код с веб-страницы RubyForge. IronRuby, реализованный в C# проект с открытым кодом, является прекрасным примером реализации динамического языка. IronPython в качестве проекта с открытым кодом размещен на веб-сайте CodePlex; в него включен пример языка с названием ToyScript на случай, если вы пожелаете ознакомиться с работой DLR.

Для обеспечения постоянно сохраняющейся совместимости с базовой платформой Ruby группа IronRuby использует RubySpecs. Это набор примеров для общего использования, основанный на рекомендованных способах реализации языка Ruby. RubySpecs предназначен для обеспечения одинакового поведения различных реализаций, включая Matz's Ruby Interpreter (MRI), JRuby, MacRuby и IronRuby. В RubySpecs используется синтаксически совместимая версия RSpec с названием MSpec. Они рассматриваются как приемочные тесты для реализации IronRuby.

Тестирование приложения C# с помощью IronRuby

В течение многих предшествующих лет значение теории и практики TDD для разработки программных продуктов возрастало. Результатом применения TDD был высококачественный с точки зрения проектных решений и удобства сопровождения код наряду с небольшим числом попутных недостатков. Используя вместо TDD подход BDD, я могу, имея IronRuby, использовать платформу спецификаций RSpec и модуль выполнения для предоставления примеров работы моих объектов C#.

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

Это важное отличие по сравнению с платформами модульного тестирования, такими как NUnit и MbUnit. Обе они используют атрибуты тестов для указания на то, что метод является тестом для системы. В RSpec используется другой подход. В RSpec постулируется, что каждый метод является примером запланированного характера работы кода. Хотя это различие довольно тонкое, оно меняет способ написания примеров, в том числе и используемую терминологию, и способ организации методов, и легкость восприятия концепции по сравнению с TDD. Используя BDD и RSpec наряду с тесной интеграцией IronRuby и .NET Framework, можно приступать к применению IronRuby для тестирования приложений C#. Классическим примером RSpec является игра «Боулинг».

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

require File.dirname(__FILE__) + \
  '/InteropSamples/Bowling/Bowling/bin/Debug/bowling.dll'

Затем необходимо получить доступ к RSpec.

require 'rubygems'
require 'spec'

Теперь можно приступать к написанию примеров. Вот пример, показывающий, как должна работать реализация для боулинга. У RSpec имеется доменный язык (Domain Specific Language — DSL), которого необходимо придерживаться, чтобы примеры были исполняемыми. Первой частью DSL является блок describe. Здесь вы просто указываете объект, который вы «описываете», вместе с необязательным описанием. В данном случае определяется объект Bowling, который будет реализовываться на языке C#.

describe Bowling, " defines the bowling game" do

Для повышения удобочитаемости вся настройка будет выполняться в блоке before.

  before(:each) do  
    @bowling = Bowling.new 
  End

С этого момента можно взаимодействовать с объектом, создавать пример и проверять правильность его работы. Я использую блок «it», предоставляя строку, определяющую контекст примера и предмет демонстрации. Затем пишу раздел кода, который взаимодействует с системой и проверяет, правильное ли выполнено действие.

  it "should score 0 for a gutter game" do
    20.times { @bowling.hit(0) }
    @bowling.score.should == 0
  end
end

Реализация на языке C# выглядит следующим образом.

public class Bowling {
  public int Score { get; set; }
  public void Hit(int pins)
    { Score += pins; }
}

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

>ir bowling_spec.rb
.
Finished in 1.0458315 seconds
1 example, 0 failures

Если бы мне требовался более подробный отчет, можно было бы выбрать формат specdoc. Далее выводится описание объекта наряду со всеми примерами и сообщением о том, прошли они проверку или нет.

>ir bowling_spec.rb --format specdoc
Bowling defines the bowling game
- should score 0 for a gutter game
Finished in 1.43728 seconds
1 example, 0 failures

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

Для загрузки исходного кода вам потребуется установить клиент управления исходным кодом Git, например msysgit. Средство управления исходным кодом IronRuby доступно в интерактивном режиме. Если вам требуется дополнительная информация, рекомендую посетить веб-узел проекта IronRuby или ознакомиться в моеме блоге с сообщением «Загрузка IronRuby с GitHub». После загрузки исходного кода можно компилировать сборку в Visual Studio с помощью файла решения IronRuby.sln или, если у вас установлен MRI, можно выполнить следующую команду.

rake compile

После компиляции IronRuby необходимо загрузить различные библиотеки, например RSpec, для получения дополнительных функциональных возможностей. В Ruby используется концепция RubyGems (жемчужины Ruby), в которой «жемчужины» представляют собой пакеты, которые можно загружать для получения дополнительных функциональных возможностей и дополнительных зависимостей. Для загрузки RSpec введите в командной строке следующую команду.

gem install rspec

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

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

Получив правильные двоичные файлы, вы найдете среди них ir.exe — интерпретатор IronRuby, с помощью которого можно выполнять код. Достаточно запустить приложение из командной строки, и вы окажетесь в среде интерактивной консоли. В Ruby код выполняется построчно, что прекрасно подходит для изучения и отладки, а также для выполнения коротких команд для решения повседневных задач. Если передать имя файла в качестве параметра, этот файл исполняется, и результаты выводятся на консоль.

Продвигаясь вперед

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

Бен Хол (Ben Hall) является разработчиком и тестером программ на C#. Он страстно увлечен разработкой программных средств и обожает писать код. Бен работает в компании Red Gate Software (Великобритания) инженером-испытателем и увлеченно исследует различные способы тестирования программных средств, как автоматизированного тестирования, так и тестирования вручную, уделяя основное внимание оптимальным способам тестирования приложений разных типов. Бену присвоен статус MVP по C# и он ведет блог по адресу Blog.BenHall.me.uk.