Este artigo foi traduzido por máquina.

Execução de teste

Teste de solicitação-resposta usando o IronPython

James McCaffrey

Baixe o código de exemplo

James McCaffreyEu sou grande fã do uso da linguagem de programação Python para diversos tipos de tarefas de automação de teste leve. Na coluna deste mês, mostro como usar a IronPython — uma implementação compatível com o Microsoft .NET Framework do Python — para executar a solicitação-resposta HTTP de teste para aplicativos da Web do asp.net.

Especificamente, eu crio um script de estrutura de teste curto que simula um usuário usando um aplicativo asp.net. Equipamento de IronPython programaticamente posta informações de solicitação HTTP para o aplicativo em um servidor Web. Ela busca, em seguida, o fluxo de resposta HTTP
e examina o texto em HTML para um valor esperado de algum tipo para determinar um resultado de aprovação/reprovação. Bem como sendo um útil
técnica de teste no seu próprio direito, aprender a executar a solicitação-resposta HTTP testes com a IronPython é uma excelente maneira de aprender sobre a linguagem de IronPython.

Esta coluna pressupõe que você tiver familiaridade básica com a tecnologia asp.net e o intermediárias técnicas de scripts com uma linguagem como, por exemplo, JavaScript, o Windows PowerShell, VBScript, Perl, PHP ou Ruby, mas eu não suponha que você tem qualquer experiência com o Python. No entanto, mesmo se estiver familiarizado com o asp.net e de script, você ainda deve ser capaz de acompanhar a coluna sem muita dificuldade. A melhor maneira de ver o que eu estou direcionamento é examinar as capturas de tela do figuras 1 e 2 do .

A Figura 1 ilustra o exemplo de aplicativo da Web do asp.net em teste. O sistema em teste é uma Web simples mas representativa
aplicativo chamado MiniCalc. Eu deliberadamente mantido meu aplicativo Web do asp.net em teste mais simples possível para que eu não oculte os pontos-chave na automação de teste de IronPython. Aplicativos da Web reais são significativamente mais complexos que o aplicativo MiniCalc fictício mostrado no do Figura 1, mas a técnica de teste do IronPython que descrevo aqui facilmente generalizou para aplicativos complexos. O aplicativo MiniCalc Web aceita dois valores numéricos, uma indicação para adicionar ou multiplicar os valores e o número de casas decimais para exibir a resposta. O aplicativo, em seguida, envia os valores para um servidor Web, onde o resultado é calculado. O servidor cria a resposta HTML e o envia de volta para o navegador do cliente, no qual o resultado é exibido ao número de casas decimais, especificado pelo usuário.

Figure 1 MiniCalc Web App Under Test

Figura 1 do aplicativo Web MiniCalc sob teste

A Figura 2 mostra uma estrutura de teste do IronPython em ação. O meu script é denominado harness.py e não aceita argumentos da linha de comando. Para manter a simplicidade, eu tenho informações embutidos, incluindo a URL do aplicativo da Web e o nome do arquivo de entrada do caso de teste. Minha estrutura começa exibindo a URL de destino de http://localhost/minicalc/default.aspx. No caso de teste 001, minha estrutura programaticamente posta informações que corresponde a um usuário digitando 1,23 no controle TextBox1, digitando 4.56 em TextBox2, selecionando o RadioButton1 (para indicar uma operação de adição), selecionando o controle DropDownList1 4 e clicando no Button1 (para calcular). Nos bastidores, o equipamento de captura a resposta HTTP do servidor Web e, em seguida, procura a resposta uma indicação de que 5.7900 (a soma correta de decimais 1,23 e 4.56 a 4) está no controle TextBox3 resultado. As faixas de equipamento de casos, o número de teste essa passagem e o número de falhas e exibe esses resultados após o processamento de todos os casos de teste.

Figure 2 Testing the App Using IronPython

De teste de aplicativos usando o IronPython, a Figura 2

Nas seções a seguem, descreva brevemente o aplicativo Web sob teste para que você saiba exatamente o que está sendo testado. Em seguida, eu orientá os detalhes da criação de automação leve de solicitação-resposta HTTP usando o IronPython. Concluir, apresentando algumas opiniões sobre quando a utilização de IronPython é adequada e quando outras técnicas são mais apropriadas. Eu acho que você encontrará as informações interessantes e uma adição útil para o conjunto de ferramentas de teste.

O aplicativo em teste

Let’s dê uma olhada no código do aplicativo da Web do ASP.NET MiniCalc, que é o destino da minha automação de teste. Eu criei o aplicativo usando o Visual Studio 2008. Depois de iniciar o Visual Studio com privilégios de administrador, cliquei no arquivo | novo | site da Web. Para evitar o mecanismo de code-behind do asp.net e manter todo o código do meu aplicativo Web em um único arquivo, eu selecionei a opção site vazio. Especifiquei http://localhost/MiniCalc no campo de localização. Decidi usar c# para o aplicativo MiniCalc, mas a estrutura de teste, que eu me apresentar nessa coluna funciona com aplicativos asp.net, vb.net escritos e com pequenas modificações que no equipamento pode direcionar aplicativos Web escritos usando tecnologias como, por exemplo, clássica ASP, CGI, PHP, JSP e Ruby. Eu clicar em OK na caixa de diálogo New Web Site para gerar a estrutura do meu aplicativo Web. Em seguida, eu entrou para a janela do Solution Explorer, right-clicked no nome do projeto MiniCalc e selecionada no menu de contexto Add New Item. Eu selecionado do formulário da Web da lista de modelos instalados e aceita o nome do arquivo default. aspx. Eu desmarcado a opção “ Place code in separate file ” e, em seguida, clicar no botão Adicionar. Em seguida, eu duas vezes no nome do arquivo default. aspx no Solution Explorer para editar o código gerado pelo modelo. Eu excluir todo o código de modelo e substituído com o código mostrado na do Figura 3.

Do Código MiniCalc, a Figura 3

<%@ Page Language="C#" %>
<script runat="server">
  private void Button1_Click(object sender, System.EventArgs e)
  {
    double alpha = double.Parse(TextBox1.Text.Trim());
    double beta = double.Parse(TextBox2.Text.Trim());

    string formatting = "F" + DropDownList1.SelectedValue;

    if (RadioButton1.Checked)
      TextBox3.Text = Sum(alpha, beta).ToString(formatting);
    else if (RadioButton2.Checked)
      TextBox3.Text = Product(alpha, beta).ToString(formatting);
    else
     TextBox3.Text = "Select method";
  }
  private static double Sum(double a, double b)
  {
    return a + b;
  }
  private static double Product(double a, double b)
  {
    return a * b;
  }
</script>

<html>
  <head>
    <style type="text/css">
     fieldset { width: 16em }
     body { font-size: 10pt; font-family: Arial }
    </style>
    <title>Default.aspx</title>
    </head>
  <body bgColor="#ccffff">
    <h3>MiniCalc by ASP.NET</h3>
    <form method="post" name="theForm" id="theForm" runat="server" action="Default.aspx">
      <p><asp:Label id="Label1" runat="server">Enter number:&nbsp</asp:Label>
      <asp:TextBox id="TextBox1" width="100" runat="server" /></p>
      <p><asp:Label id="Label2" runat="server">Enter another:&nbsp</asp:Label>
      <asp:TextBox id="TextBox2" width="100"  runat="server" /></p>
      <p></p>
      <fieldset>
        <legend>Arithmentic Operation</legend>
     <p><asp:RadioButton id="RadioButton1" GroupName="Operation" runat="server"/>Addition</p>
    <p><asp:RadioButton id="RadioButton2" GroupName="Operation" runat="server"/>Multiplication</p>
        <p></p>
      </fieldset>
    <p>Decimals:   
      <asp:DropDownList ID="DropDownList1" runat="server">
      <asp:ListItem>3</asp:ListItem>
      <asp:ListItem>4</asp:ListItem>
      </asp:DropDownList>
    </p>
      <p><asp:Button id="Button1" runat="server" text=" Calculate " onclick="Button1_Click" /></p>
      <p><asp:TextBox id="TextBox3" width="120"  runat="server" />
    </form>
  </body>
</html>

Para manter meu código-fonte de tamanho pequeno e fácil de entender, eu estou tomando atalhos como, por exemplo, não realizando verificação de erros e a combinação de controles de servidor (por exemplo, < asp: TextBox >) com HTML sem formatação (como <fieldset>). As partes mais importantes do código de do Figura 3 são as IDs dos controles de servidor asp.net. Usar o padrão de identificações de Label1 (prompt do usuário), TextBox1 e TextBox2 (entrada de dois números), RadioButton1 e RadioButton2 (opção de adição ou multiplicação) DropDownList1 (número de casas decimais para o resultado), Button1 (calcular) e TextBox3 (resultado). Para executar automatizada solicitação-resposta HTTP de teste para um aplicativo asp.net usando a técnica que apresento aqui, você deve conhecer as IDs dos controles do aplicativo. Nesse caso, eu tenho o código-fonte disponível porque estou criando o aplicativo por conta própria;mas mesmo se você estiver testando um aplicativo da Web, que você não escreveu, você sempre pode examinar o aplicativo usando a funcionalidade de modo de exibição de fonte de um navegador da Web.

Para verificar que o meu aplicativo Web sob teste foi criado corretamente, eu <F5> de ocorrênciaschave. Eu clicar em OK da caixa de diálogo Debugging Not Enabled resultante para instruir o Visual Studio para modificar o arquivo de Web. config do aplicativo da Web. O Visual Studio, em seguida, iniciado o Internet Explorer e carregado MiniCalc. Observe que o atributo de ação do meu <form>elemento é definido como default. aspx. Em outras palavras, sempre que um usuário envia uma solicitação, o mesmo código de página default. aspx é executado. Isso permite que meu aplicativo MiniCalc Web a sensação de um único aplicativo em vez de uma seqüência de diferentes páginas da Web. Como o HTTP é um protocolo sem estado, o asp.net realiza o efeito da aplicação, mantendo o estado do aplicativo da Web em um tipo de valor especial de oculto chamado ViewState. Como você verá em breve, lidar com ViewState um aplicativo asp.net é uma das chaves de dados para o aplicativo de lançamento por meio de programação.

Solicitação-resposta asp.net teste com a IronPython

Let’s ultrapassar o programa de equipamento de teste do IronPython que produziu a captura de tela em do Figura 2. IronPython é um download gratuito disponível no CodePlex, o projeto de código-fonte aberto patrocinados pela Microsoft em ironpython.codeplex.com de . Estou usando a versão 2.6.1, que é executado na versão 2. 0 do .NET Framework e é executado em qualquer computador que ofereça suporte a essa versão do Framework. A estrutura geral do meu script de estrutura de teste é apresentada no do Figura 4.

Do estrutura do conjunto de teste, a Figura 4

set up imports
define helper functions

try:
  initialize variables
  open test case data file
  loop
    read a test case from file
    parse test case data
    determine ViewState
    determine EventValidation
    construct request string
    send request string to app
    fetch response from app
    determine if response has expected result
    print pass or fail
  end loop
  close test case data file
  print summary results
except:
  handle exceptions

Como você pode ver, meu script de estrutura é simples e é orientada por um arquivo de dados do caso de teste externos. Esse arquivo de dados do caso de teste é denominado testCases.txt e consiste em:

001|1.23|4.56|RadioButton1|4|clicked|5.7900
002|1.23|4.56|RadioButton2|4|clicked|5.7900
003|2.00|3.00|RadioButton1|4|clicked|5.0000

Cada linha representa um caso de teste e tem sete campos delimitados por um “ | ” caracteres. O primeiro campo é uma ID de caso de teste. Os segundo e terceiro campos são entradas de TextBox1 e TextBox2. O quarto campo codifica a solicitar a adição ou multiplicação. O quinto campo é o valor para o controle DropDownList decimais. O campo sexto (“ clicado ”) é o evento de Button1. O campo sétimo é o resultado esperado, o que deve aparecer na TextBox3. O segundo caso de teste é deliberadamente incorreto apenas para demonstrar uma falha no caso de teste. Para o leve que eu estou descrevendo aqui de abordagem de teste, um arquivo de texto simples para armazenar dados de caso de teste geralmente é uma boa opção. Se eu quisesse incorporar dados do meu caso de teste diretamente no script de estrutura, eu poderia ter feito isso usando uma matriz de cadeias de caracteres como:

testCases = ['001|1.23|4.56|RadioButton1|4|clicked|5.7900',
             '002|1.23|4.56|RadioButton2|4|clicked|5.7900',
             '003|2.00|3.00|RadioButton1|4|clicked|5.0000']

e, em seguida, iteramos por meio de cada caso de teste como:

for line in testCases:
  ...

Python também tem um tipo de lista que pode ser usado para armazenar dados de caso de teste.

As três primeiras linhas do meu conjunto de teste da IronPython são:

# harness.py
import sys
import clr

Os comentários em Python começam com o caractere “ # ” e estendem o final da linha. A instrução “ Importar sys ” permite que o meu script para acessar recursos no módulo de sys especial do IronPython.

Os locais desses recursos podem ser listados, emitindo um comando sys.path a partir do console interativo da IronPython. A instrução “ importação clr ” permite que o meu script acessar e usar a funcionalidade do .NET CLR principal.

Minhas instruções próximos seis explicitamente habilitar a funcionalidade do .net que minha estrutura usa:

from System import *
from System.IO import *
from System.Text import *
from System.Net import *
clr.AddReference('System.Web')
from System.Web import *

A primeira linha importa o sistema e é semelhante à instrução “ usando o sistema ” em um programa c#. A instrução “ Importar clr ” inclui o namespace System, portanto, eu poderia omitir a “ na importação de sistema * ” instrução, mas eu prefiro para deixá-la no como uma forma de documentação. As próximas três instruções levam a System. IO (para operações de arquivo), System. Text (para conversão de byte) e namespaces System.net (para solicitação de ­ resposta funcionalidade) para o escopo. A “ clr.AddReference (‘ Sys ­ tem.Web ’) ” declaração traz o namespace System. Web para o escopo. Este namespace não está acessível diretamente por padrão, portanto, eu deve usar o método Adicionar referência antes de eu emito a “ na importação de System. Web * ” instrução para que eu possa acessar os métodos de codificação de URL.

Em seguida, defino um método auxiliar para buscar as informações de ViewState para o aplicativo Web sob teste:

def getVS(url):
  wc = WebClient()
  bytes = wc.DownloadData(url)
  html = Encoding.ASCII.GetString(bytes)
  start = html.IndexOf('id="__VIEWSTATE"', 0) + 24
  end = html.IndexOf('"', start)
  vs = html.Substring(start, end-start)
  return vs

Lembre-se de que, como o HTTP é um protocolo sem estado, o asp.net dá o efeito de ser um aplicativo com monitoração de estado ao manter o estado do aplicativo em um valor oculto chamado ViewState. Um valor ViewState é uma seqüência de caracteres codificada na Base64 que mantém o estado de uma página asp.net através de vários idas e voltas de solicitação/resposta. Da mesma forma, um valor EventValidation foi adicionado no asp.net 2. 0 e é usado para fins de segurança para ajudar a impedir ataques de inserção de script. Esses dois mecanismos são essenciais para programaticamente enviar dados para um aplicativo da Web do asp.net.

Python, você deve definir funções antes de chamá-los em um script. Funções são definidas usando a palavra-chave def. Primeiro, a função auxiliar instancia um objeto WebClient. Em seguida, o método DownloadData envia uma solicitação HTTP para o aplicativo da Web fornecido pelo parâmetro de url e a resposta HTTP de busca como uma matriz de valores de bytes. Eu uso o método GetString para converter bytes em uma seqüência de caracteres chamada html. Um elemento de ViewState tem esta aparência:

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE"
 value="/wEPDwULLTEwNjU=" />

Dessa forma, para extrair o valor, primeiro determinar o local do id de subseqüência de caracteres = "_ _ VIEWSTATE" e, em seguida, adicione 24 caracteres. Essa abordagem é frágil no sentido de que a técnica serão desfeitos se o asp.net altera o formato da seqüência de caracteres do ViewState, mas como essa automação leve, simplicidade supera a robustez. Determinar qual é o caractere de aspas duplas terminação e, em seguida, posso usar o método substring para extrair o valor ViewState. Ao contrário da maioria dos idiomas, quais símbolos de uso, como iniciar... end ou {...} para delimitar blocos de código, o Python utiliza recuo. Se você é novato em programação Python, isso pode parecer estranho em primeiro lugar, mas a maioria dos engenheiros que conversei para dizer que rapidamente se tornar utilizado a sintaxe. Python é suportada por um conjunto de módulos, portanto, uma alternativa ao uso de métodos do .net para recuperar o valor ViewState é usar as funções do módulo de urllib nativa do Python.

Depois de definir a função de auxiliar getVS, eu defino uma função auxiliar para obter o valor EventValidation:

def getEV(url):
  wc = WebClient()
  bytes = wc.DownloadData(url)
  html = Encoding.ASCII.GetString(bytes)
  start = html.IndexOf('id="__EVENTVALIDATION"', 0) + 30
  end = html.IndexOf('"', start)
  ev = html.Substring(start, end-start)
  return ev

Eu uso a mesma técnica para extrair EventValidation como faço para extrair o ViewState. Observe que o Python é uma linguagem dinâmica digitada, para que eu não especificar os tipos de dados de meu parâmetros, variáveis e objetos. Por exemplo, DownloadData retorna uma matriz de bytes IndexOf retorna um inteiro e o intérprete de IronPython irá descobrir esses tipos para mim. Definindo duas funções, getVS e getEV, exige duas chamadas de ida e volta para o aplicativo Web sob teste, portanto, talvez você queira combinar as duas funções do auxiliar em um nome e a única função auxiliar que algo como getVSandEV(url).

Depois de definir minhas funções auxiliares, minha automação real começa:

try:
  print '\nBegin IronPython Request-Response testing'
  url = 'http://localhost/MiniCalc/Default.aspx'
  print '\nURL under test = ' + url + '\n'
  testCases = 'testCases.txt'
  ...

Ao contrário de alguns idiomas exigem um ponto de entrada, como, por exemplo, um método Main, a execução de scripts Python simplesmente começa com a primeira instrução executável. Eu uso a palavra-chave tente capturar quaisquer exceções, em seguida, imprimir uma mensagem de inicialização. Python permite o uso de aspas simples ou de aspas duplas para definir a seqüência de caracteres literais e as seqüências de escape, como \n podem ser incorporadas com um delimitador. Para desativar a avaliação da seqüência de escape, você pode colocar literais de seqüência de caracteres com letra minúscula r (“ bruta ”), por exemplo: arquivo = r'\newFile.txt '. Eu embutir a URL do aplicativo em teste e exibir esse valor para o shell. Se eu quisesse ler a URL da linha de comando, eu poderia ter usado a matriz sys.argv internos, por exemplo: URL = sys.argv[1]. Python usa o caractere “ + ” para concatenação de cadeia de caracteres. Eu também embutir o nome do meu teste caso o arquivo de dados e como eu não incluir informações de caminho do arquivo, eu faço a suposição de que o arquivo está no mesmo diretório que o script de IronPython.

Em seguida, eu configurar contadores, abrir Meu arquivo de dados do caso de teste e iniciar a iteração por meio do arquivo:

...
numPass = numFail = 0
fin = open(testCases, 'r')
for line in fin:
  print '==========================================='
  (caseid,value1,value2,operation,decimals,action,expected) = 
    line.split('|')
  ...

Python tem vários idiomas que gosto, incluindo vários atribuição de variável e a sintaxe do arquivo concisa de operações. Significa que o argumento “ r ” na chamada à função de abertura abrir o arquivo para leitura. A instrução “ para a linha em Nadadeira ” enumera através do arquivo de uma linha por vez, atribuindo a linha atual de entrada para a variável “ linha ”. Outra construção elegantes do Python é o idioma de tupla. Tuplas são identificadas usando esquerda e parênteses à direita e os valores de tupla são delimitados pela “ ” caracteres. Aqui, eu chamo o método de divisão e atribua cada resultantes de token para variáveis caseid, valor1, valor2, operação, casas decimais, ação e esperado, tudo em uma única instrução. Muito bem.

Em seguida, começar a criação de dados para enviar para o aplicativo Web sob teste:

...
expected = 'value="' + expected.Trim() + '" id="TextBox3"'
data = 'TextBox1=' + value1 + '&TextBox2=' + value2 + '&Operation=' +
 operation + '&DropDownList1=' + decimals + '&Button1=' + action

print 'Test case: ' + caseid
print 'Input    : ' + data
print 'Expected : ' + expected
...

Posso modificar um pouco a variável esperada para se parecer com algo parecido com:

value="5.7900" id="TextBox3"

Portanto, quando procuro a resposta HTTP, serei mais específico do que simplesmente procurando “ 5.7900 ”. Associo meus valores de entrada do caso de teste para seus respectivos controles como pares de nome-valor conectados pela “ & ” caracteres. Os duas primeiras pares nome-valor de seqüência de caracteres de postagem simplesmente definir TextBox1 e TextBox2 para valor1 e valor2 dos dados de caso de teste. O terceiro par nome / valor (por exemplo, operation = RadioButton1) é como simulo um usuário selecionando um controle RadioButton, neste caso, o controle que corresponde à adição. Você deve ter adivinhado incorretamente (como eu fiz originalmente) que a forma de definir o botão de opção seria usar uma sintaxe semelhante RadioButton1 = marcada. Mas RadioButton1 é um valor do controle operation, e não um controle. O quinto par nome-valor, Button1 = clicado, é um pouco enganador. Eu preciso fornecer um valor para Button1 indicar que o controle for clicado, mas qualquer valor irá funcionar, portanto, eu poderia ter usado Button1 = foo (ou mesmo apenas Button1 =), mas Button1 = clicado é mais descritivo na minha opinião. Eu echo os valores que eu tenha analisado a partir dos dados do caso de teste para o shell de comando, fazendo uso do operador de concatenação de cadeia de caracteres “ + ”.

Em seguida, posso lidar com os valores ViewState e EventValidation:

...
vs = getVS(url)
ev = getEV(url)
vs = HttpUtility.UrlEncode(vs)
ev = HttpUtility.UrlEncode(ev)
data = data + "&__VIEWSTATE=" + vs + "&__EVENTVALIDATION=" + ev
...

Eu chamo as funções do auxiliar getVS e getEV definidas anteriormente. Os valores ViewState e EventValidation são cadeias de caracteres codificada em Base64. Codificação Base64 usa 64 caracteres: A-Z de maiúsculas, minúsculas da-z, dígitos de 0 a 9, o caractere “ + ” e o caractere “ / ”. O caractere “ = ” é usado em Base64 para preenchimento. Porque alguns dos caracteres usados na Base64 não são permitidos em um fluxo de solicitação HTTP, usarei o método HttpUtility.UrlEncode do namespace System. Web para converter caracteres importunos em uma seqüência de três caracteres que comece com o caractere “ % ”.

Por exemplo, um bruto “ > ” caractere é codificado como % 3D e um espaço em branco é codificado como % 20. Quando um servidor Web recebe uma solicitação HTTP que contêm qualquer uma das seguintes seqüências de três caracteres especiais, o servidor decodifica as seqüências de volta para a entrada bruta. Após a codificação, eu acrescentar os valores ViewState e EventValidation para os dados de postagem.

Em seguida, eu processar os dados de postagem para prepará-lo para uma solicitação HTTP:

...
buffer = Encoding.ASCII.GetBytes(data)
req = HttpWebRequest.Create(url)
req.Method = 'POST'
req.ContentType = 'application/x-www-form-urlencoded'
req.ContentLength = buffer.Length
...

Usarei o método GetBytes do namespace System. Text para converter dados do meu Post em uma matriz de bytes chamada buffer. Em seguida, crio um novo objeto HttpWebRequest, usando um método Create explícito. Posso fornecer valores para as propriedades do método, ContentType e ContentLength do objeto HttpWebRequest. Você pode considerar o valor do ContentType como uma seqüência de mágica, é necessária para lançar uma solicitação de HTTP.

Em seguida, posso enviar a solicitação HTTP:

...
reqst = req.GetRequestStream()
reqst.Write(buffer, 0, buffer.Length)
reqst.Flush()
reqst.Close()
...

O padrão de programação para enviar uma solicitação pode parecer um pouco estranho se você estiver familiarizado com a técnica. Em vez de usar um método de envio explícito de algum tipo, você cria um objeto de fluxo e, em seguida, usa um método de gravação.

O método de gravação requer uma matriz de bytes, o índice da matriz para começar a escrever e o número de bytes a gravar. Ao usar 0 e buffer.Length, escrevo todos os bytes no buffer. O método Write, na verdade, não envia a postagem para o servidor da Web;Você deve forçar o envio de chamando o método de liberação. O método Close realmente chama o método flush, minha chamada para Flush não é necessário nessa situação, mas que incluem a chamada para fins de esclarecimento.

Depois de enviar a solicitação HTTP, posso buscar a resposta associada:

...
res = req.GetResponse()
resst = res.GetResponseStream()
sr = StreamReader(resst)
html = sr.ReadToEnd()
sr.Close()
resst.Close()
...

O método GetResponse retorna o objeto HttpWebResponse associado a um objeto HttpWebRequest. O objeto de resposta pode ser usado para criar um fluxo e, em seguida, posso associar o fluxo de um objeto StreamReader e use o método ReadToEnd para buscar o fluxo de resposta inteira como uma única cadeia de caracteres. Embora os mecanismos de limpeza do .NET Framework subjacentes eventualmente fecharia os StreamReader e fluxo de objetos para você, eu prefiro explicitamente fechá-los.

Em seguida, posso examinar a resposta HTTP para o valor esperado de casos de teste:

...
if html.IndexOf(expected) >= 0:
  print 'Pass'
  numPass = numPass + 1
else:
  print '**FAIL**'
  numFail = numFail + 1
...

Eu uso o método IndexOf para pesquisar a resposta HTTP. Como IndexOf retorna o local do início da cadeia de caracteres de pesquisa dentro da seqüência de referência, um valor de retorno > = 0 significa que a seqüência de caracteres de pesquisa é a seqüência de caracteres de referência. Observe que, ao contrário de muitas linguagens, Python não têm o incremento ou decrementar operadores, como + + numPass.

Em seguida, eu terminar meu script:

...
print '===============================\n'
    # end main processing loop
  fin.close()
  print '\nNumber pass = ' + str(numPass)
  print 'Number fail = ' + str(numFail)  
  print '\nEnd test run\n'
except:
  print 'Fatal: ', sys.exc_info()[0]
# end script

Posso colocar um comentário no final do loop “ para ” que itera através de cada linha do arquivo de dados do caso de teste como um auxílio para fazer se que meu recuo está correto. Uma vez fora do loop, posso fechar o arquivo de dados do caso de teste e a passagem de impressão e contadores de falhar. Observe que, como numPass e numFail foram inferidos para ser do tipo int, eu deve convertê-los para digitar “ seqüência ” usando a função str de Python, de modo que eu possa concatená-las. Minha estrutura termina ao manipular exceções lançadas no bloco try simplesmente ao imprimir a mensagem de exceção genérica armazenada na matriz interna sys.exec_info.

Automação rápida com um tempo de vida curta

O exemplo que apresentei aqui deve fornecer informações suficientes para escrever automação de teste de IronPython para seus próprios aplicativos da Web. Existem várias alternativas ao uso de IronPython. Na minha opinião, a IronPython é mais adequada para a automação de teste leve onde você deseja criar a automação de forma rápida e a automação tem um tempo de vida curta (alguns dias ou semanas) desejado. Minha técnica tem algumas limitações – em particular não é possível facilmente lidar com aplicativos da Web que geram as caixas de diálogo pop-up.

Uma das vantagens de usar a IronPython para automação de teste leve em comparação com outras linguagens de script, é que você pode usar o console interativo para emitir comandos para ajudá-lo a criar o script. Além disso, existem vários editores interessantes e até mesmo, é possível encontrar SDKs do IronPython que permitem a você integrar o Iron ­ Python no Visual Studio. Pessoalmente, quando vou escrever automação de teste do aplicativo da Web, caso eu queira desenvolver uma estrutura relativamente curta, eu considero usando o IronPython e o bloco de notas. Se, vou escrever um equipamento que tenha mais de três páginas de código, no entanto, geralmente uso c# e Visual Studio.

Dr. James McCaffrey trabalha para a Volt Information Sciences Inc. onde gerencia o treinamento técnico para engenheiros de software trabalham em Redmond da Microsoft, Wash., campus. Ele trabalhou em vários produtos da Microsoft, incluindo o Internet Explorer e o MSN Busca. McCaffrey é autor do livro “ .NET Test Automation Recipes: Uma abordagem de solução de problemas ” (Apress, 2006). Ele pode ser contatado em jammc@microsoft.com de .

Graças aos seguintes especialistas técnicos para revisão deste artigo: de Dave Fugate e de Paul Newson