Введение в тестирование 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, epaCryptoHashServiceClient 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 **");
}