Параметризация закодированных запросов веб-сервиса

Я пытаюсь параметризовать запросы веб-службы в тесте веб-производительности. Используя Fiddler2, я записал последовательность из более чем 60 запросов веб-службы для транзакции, выполняемой моим настольным приложением, и сохранил их в виде файла .webtest. Этот веб-тест проходит без каких-либо ошибок, и ответы, которые я проверил, выглядят правильно.

Когда запросы веб-службы просматриваются в Visual Studio 2012, они отображаются в виде простого текста, поэтому я должен иметь возможность редактировать их, чтобы параметризовать значения в запросах SOAP. Например, большинство запросов содержат текст <Database>db1a</Database> (на самом деле он имеет &lt;Database&gt;db1a&lt;/Database&gt;), и я хочу изменить их, чтобы получить имя базы данных из параметра контекста. Есть несколько других элементов, которые нужно заменить параметрами. Для этой одной транзакции имеется более 60 запросов к веб-службе, и у меня есть другие транзакции для записи. Файл .webtest содержит XML, а запросы выглядят так:

<Request Method="POST" Version="1.1" Url="http://example.com/somewhere.asmx" ThinkTime="83" Timeout="60" ParseDependentRequests="True" FollowRedirects="True" RecordResult="True" Cache="False" ResponseTimeGoal="0" Encoding="utf-8">
  <Headers>
    <Header Name="Content-Type" Value="text/xml; charset=utf-8" />
    <Header Name="SOAPAction" Value="&quot;http://example.com/webservices/VariousActionNamesHere&quot;" />
  </Headers>
  <StringHttpBody ContentType="text/xml; charset=utf-8">PAA/AHgAbQBsACAAdg
        ... lots more characters not shown
        +AA==</StringHttpBody>
</Request>

Поле StringHttpBody содержит закодированную версию запроса SOAP. Visual Studio показывает его как обычный текст. Какова кодировка этого поля и как я могу его декодировать и кодировать?

Я установил выпуск 3.0 «Плагины веб-тестирования и нагрузочного тестирования для Visual Studio Team Test» с сайта http://teamtestplugins.codeplex.com/ . Они обеспечивают немного лучший интерфейс для редактирования запросов SOAP по одному. Но они не допускают массовых изменений.

Преобразование веб-теста в закодированный веб-тест (т. е. в C#) показывает запросы SOAP в виде простого текста, и их можно редактировать там, но я бы предпочел сохранить гибкость файла .webtest.

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


person AdrianHHH    schedule 14.10.2013    source источник


Ответы (3)


StringHttpBody кодируется base64. Необработанное тело запроса преобразуется в массив байтов UTF-16, а затем кодируется base64, например:

Convert.ToBase64String(Encoding.Unicode.GetBytes(oSession.GetRequestBodyAsString()));

Для быстрого просмотра вы можете скопировать/вставить эту строку на экран Инструменты Fiddler > TextWizard, а затем использовать параметр From Base64 для декодирования.

person EricLaw    schedule 14.10.2013
comment
Это здорово @ErikLaw. Декодирование как Base64 с помощью Fiddler показывает ромбы со знаком вопроса, чередующиеся с другими символами. Декодирование через Convert.FromBase64String() в C# дает 0x00, чередующийся с (неформально) значимыми символами Ascii. Так что это выглядит как UTF-16 в нулевой кодовой плоскости. - person AdrianHHH; 15.10.2013

Вот часть ответа на работу с полями StringHttpBody. Речь идет о декодировании и кодировании полей для облегчения понимания и модификации.

Прочитайте входной XML и найдите содержимое StringHttpBody полей. Замените содержимое каждого поля результатом вызова следующей процедуры для исходного содержимого. Запишите все строки в новый промежуточный файл. Массив байтов содержит символы UTF-16 в качестве старших и младших байтов. (Все символы, которые я видел до сих пор, имеют старший нулевой байт.)

private string DecodeBody(string source) {
    byte[] outBytes = Convert.FromBase64String(source);
    StringBuilder sb = new StringBuilder();
    Assert( (outBytes.Length % 2) != 0 );
    for (int ix = 0; ix < outBytes.Length; ix += 2) {
        Assert(outBytes[ix] != 0);
        sb.Append((char)outBytes[ix + 1]);
    }
    return sb.ToString();
}

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

source = source.Replace("&lt;Database&gt;db1a&lt;/Database&gt;", "&lt;Database&gt;{{DatabaseName}}&lt;/Database&gt;");

Затем окончательный промежуточный файл перекодируется для создания нового файла .webtest. Как и раньше, содержимое StringHttpBody полей находится и заменяется результатом вызова подпрограммы. Процедура кодирования:

private string EncodeBody(string source) {
    StringBuilder sb = new StringBuilder();
    byte[] outBytes = new byte[2 * source.Length];
    for (int ix = 0; ix < source.Length; ix++)  {
        char ch = source[ix];
        outBytes[2 * ix] = (byte)(((int)ch) & 0xFF);
        outBytes[2 * ix + 1] = (byte)((((int)ch) / 256) & 0xFF);
    }
    sb.Append(Convert.ToBase64String(outBytes));
    return sb.ToString();
}

Таким образом, поток файлов:

decode original.webtest > intermediate1
parameterise intermediate1 > intermediate2
encode intermediate2 > final.webtest

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

person AdrianHHH    schedule 20.10.2013

Для

[StringHttpBody ContentType=application/json]

Чтобы расшифровать тело:

var encodedString = childNode.InnerText;

var encodedStringBytes = Convert.FromBase64String(encodedString);

var decodedString = Encoding.Unicode.GetString(encodedStringBytes);

JObject jsonString = JsonConvert.DeserializeObject(decodedString);

Чтобы закодировать тело:

childNode.InnerText = Convert.ToBase64String(Encoding.Unicode.GetBytes(JsonConvert.SerializeObject(jsonString)));

Я думаю, это может помочь.

person raghavendrap    schedule 09.12.2013
comment
Спасибо за идеи @raghavendrap. Есть сходство с моим ответом, где вы определили некоторые библиотечные функции, которые уменьшают объем кода. Однако я не уверен, как некоторые из ваших идей подходят для сортировки параметров веб-теста производительности Visual Studio. - person AdrianHHH; 10.12.2013