Введение в тестирование WCF - Программа тестирования

ОГЛАВЛЕНИЕ

Программа тестирования

Теперь обратимся к коду для простой программы тестирования, показанному на рис. 2. По существу программа тестирования представляет собой просто клиент WCF, который отправляет входное сообщение тестируемой службе WCF и проверяет правильность возвращаемого сообщения. Начну с запуска нового экземпляра Visual Studio и создания программы консольного приложения на C# с названием TestHarness. В примере, показанном на рис. 2, обратите внимание на то, что местонахождение моей программы я задаю в виде подкаталога C:\Inetpub\wwwroot именно для того, чтобы держать код программы поблизости от тестируемой системы. Однако можно было бы поместить программу в любое другое место, включая изолированный узел для тестирования. На рис. 5 показана общая структура программы тестирования.

Рис. 5 Структура программы тестирования

using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;

namespace TestHarness
{
   class Program
   {
     static void Main(string[] args)
     {
     try
       {
         // display startup messages
         // set up test case data collection, testCases
         // set up WCF binding object, wsb
         // set up WCF address object, epa

         CryptoHashServiceClient c =
           new CryptoHashServiceClient(wsb, epa);

         foreach (TestCaseData tcd in testCases)
         {
           // echo case ID, input, expected values
           // call GetCryptoHash method, fetch return
           // compare actual return with expected
           // print pass/fail result
         }
         Console.WriteLine("\nDone");
       }
       catch (Exception ex)
       {
         Console.WriteLine("Fatal error: " + ex.Message);
       }
     }
   }

   class TestCaseData
   {
     public readonly string caseID;
     public readonly string input;
     public readonly string expected;
     public TestCaseData(string caseID, string input, string expected)
     {
       this.caseID = caseID; this.input = input; this.expected =
        expected;
     }
   }
}

Кодирование программы тестирования я начинаю с добавления оператора using, указывающего на пространство имен System.ServiceModel. В этом пространстве имен содержатся основные функции службы WCF. Далее выполняю настройку данных для теста. На рис. 5 видно, что создается простой класс TestCaseData, предназначенный для хранения идентификатора теста, входного значения и ожидаемого значения. Как я вскоре объясню, в рабочей ситуации можно было бы добавить также и другие поля, включая сведения о привязке службы WCF. Теперь данные для теста я встраиваю непосредственно в программу, создавая общий объект List и наполняя его объектами TestCaseData.

List<TestCaseData> testCases = new List<TestCaseData>();
testCases.Add(new TestCaseData("001", "Hello world",
   "E6-76-0D-55-5C-32-F6-6F-5E-15-93-31-DB-20-FD-8E"));
testCases.Add(new TestCaseData("002", "Goodbye world",
   "1A-05-3C-C0-4A-18-13-06-0E-AC-EA-BA-46-EC-CF-B1"));
testCases.Add(new TestCaseData("003", "",
   "D4-1D-8C-D9-8F-00-B2-04-E9-80-09-98-EC-F8-42-7E"));

Данные для теста можно было бы настроить во внешнем хранилище, например файле XML или таблице SQL. Здесь я использую три варианта тестовых данных, но в реальной ситуации можно было бы использовать тысячи. Наиболее сложной частью тестирования программного обеспечения является определение подходящих входных тестовых данных, заставляющих работать тестируемую систему в полную силу, и определение ожидаемых результатов.

Теперь, хотя можно написать код клиента WCF с нуля, гораздо проще для генерации кода прокси и файла конфигурации WCF использовать программу командной строки svcutil.exe, поставляемую с Visual Studio 2008. В данном случае я запускаю командную оболочку Visual Studio (которой известно местоположение svcutil.exe) и ввожу команду.

> svcutil.exe http://localhost/WCF/CryptoHashService/Service.svc

Svcutil.exe, запускаемый на выполнение с местоположением службы WCF и без каких-либо дополнительных аргументов, считывает метаданные WCF из службы и генерирует два файла. Первый файл — CryptoHashService.cs (имя целевой службы WCF, наращенное расширением .cs), содержащий код прокси на C#, который позволит отправлять сообщения и получать сообщения от моей службы WCF. Второй файл — output.config, содержащий сведения о привязке WCF (транспортный протокол, значение времени ожидания, кодировку текста и т.д.), используемые целевой службой WCF. После генерирования этих двух файлов я щелкаю правой кнопкой мыши проект программы тестирования и добавляю к нему файл CryptoHashService.cs. Вместо этого можно было бы скопировать код и вставить его непосредственно в программу тестирования.

Теперь существуют два способа использовать сведения о привязке из файла output.config. Один способ заключается в переименовании файла в файл app.config и последующем добавлении этого файла в проект клиента. Второй подход – в том, чтобы исследовать данные из файла output.config и затем написать код, программным образом назначающий объекту привязки значения, показанные в файле output.config. При написании обычной клиентской программы WCF подход с использованием app.config обычно является более предпочтительным вариантом, чем программный подход. Поскольку файл app.config представляет собой обычный текст и читается клиентской программой во время выполнения, если изменяются сведения о привязке соответствующей службы WCF, можно изменить соответствующие сведения о привязке клиента. Это делается просто внесением изменений в файл app.config и не требует перекомпилирования клиента. Однако в конкретном случае клиентской программы тестирования WCF иногда правильнее указать сведения о привязке программным способом. Программный подход позволяет легко передавать сведения о привязке в виде части входных данных для тестирования. Здесь я использую программный подход. Я создаю экземпляр объекта WSHttpBinding.

WSHttpBinding wsb = new WSHttpBinding();

Теперь присваиваю значения свойству Name и разным свойствам, относящимся ко времени, объекта привязки.

wsb.Name = "WSHttpBinding_ICryptoHashService";
wsb.CloseTimeout = TimeSpan.Parse("00:01:00");
wsb.OpenTimeout = TimeSpan.Parse("00:01:00");
wsb.ReceiveTimeout = TimeSpan.Parse("00:10:00");
wsb.SendTimeout = TimeSpan.Parse("00:01:00");

Я определяю эти значения, визуально исследуя атрибуты записи о привязке в файле output.config file, который был сгенерирован программой svcutil.exe. В данном случае я использую все значения по умолчанию, сгенерированные Visual Studio, когда создавалась служба WCF. Оставшимся свойствам привязки значения присваиваются подобным же образом.

wsb.BypassProxyOnLocal = false;
wsb.TransactionFlow = false;
wsb.HostNameComparisonMode =
   System.ServiceModel.HostNameComparisonMode.StrongWildcard;
wsb.MaxBufferPoolSize = 524288;
wsb.MaxReceivedMessageSize = 65536;
wsb.MessageEncoding =
   System.ServiceModel.WSMessageEncoding.Text;
wsb.TextEncoding = System.Text.Encoding.UTF8;
wsb.UseDefaultWebProxy = true;
wsb.AllowCookies = false;

Теперь можно настраивать объект прокси.

string uri =
   "http://vte014.vte.local/WCF/CryptoHashService/Service.svc";
EndpointAddress epa = new EndpointAddress(uri);
CryptoHashServiceClient c =
   new CryptoHashServiceClient(wsb, epa);

Класс CryptoHashServiceClient определяется в автоматически сгенерированном файле CryptoHashService.cs, созданном с помощью svcutil.exe. Этот конструктор классов принимает объект привязки (только что настроенный программно) и объект EndPointAddress, который указывает на службу WCF. Теперь экземпляр объекта клиента создан, и можно перебирать все варианты тестов и работать с тестируемой службой WCF.

На рис. 6 просто отправляется на консоль сообщение об успехе или сбое каждого из вариантов теста. В рабочей среде потребовалось бы проделать больший объем работы — отслеживать общее число успешных и сбойных случаев, возможно, отправлять сообщения по электронной почте, если один или несколько тестов закончились сбоем, сохранять результаты во внешнем хранилище данных и т.д. Если используется Team Foundation Server, данной программой тестирования можно управлять с помощью методик из моей статьи о тестировании «Пользовательская автоматизация тестирования при помощи Team System» из номера «Выпуск» за 2008 г. (см. msdn.microsoft.com/magazine/cc164248).

Рис. 6 Отображение состояния для каждого случая тестирования

foreach (TestCaseData tcd in testCases)
{
   Console.WriteLine("Case ID = " + tcd.caseID);
   Console.WriteLine("Input  = " + tcd.input);
   Console.WriteLine("Expected = " + tcd.expected);

   string actual = c.GetCryptoHash(tcd.input);
   Console.WriteLine("Actual  = " + actual);
   if (actual == tcd.expected)
     Console.WriteLine("* Pass *");
   else
     Console.WriteLine("** FAIL **");
}