├── _config.yml
├── .gitignore
├── ExemploAPI_ServeRest
├── requirements.txt
├── README.md
└── Exemplo_API_ServeRest.robot
├── ExemploSikuli
├── img
│ ├── close.png
│ ├── helloword.png
│ ├── notepad.png
│ ├── notepad_workspace.png
│ └── windows_start_menu.png
├── ExemploExecucaoRobotSikuli.mp4
└── TesteSikuli.robot
├── ExemploAutoIt
├── SEALsScript.zip
└── testeAutoIt.robot
├── ExemploLibraryXML
├── TestXML.robot
├── xmlBaseExemplo.xml
└── ResourceXML.robot
├── README.md
├── Demos
├── DemoAPI
│ ├── BDDpt-br.robot
│ ├── TestCasesAPIRequests.robot
│ └── Resource.robot
└── DemoWeb
│ ├── resources
│ ├── BDDpt-br.robot
│ └── ResourceBDD.robot
│ └── testes
│ └── TestCasesBDDExemplo.robot
├── ExemploBDD
├── BDDpt-br.robot
├── TestCasesBDDExemplo.robot
└── ResourceBDD.robot
├── SuitePalestraGUTS
├── SuiteExemploAPI
│ ├── BDDpt-br.robot
│ ├── TestCasesAPIRequests.robot
│ └── Resource.robot
└── SuiteExemploWEB
│ ├── TestCasesCadastroQANinja.robot
│ └── ResourceCadastroQANinja.robot
├── ExemploPabot
├── TestCaseLoginChrome.robot
├── TestCaseLoginFirefox.robot
└── Resource_steps_login.robot
├── ExemploMyCustomLibrary
├── libraries
│ └── decode64.py
└── TestCaseExemploMyCustomLibrary.robot
├── ExemploSelenium
├── TestCasesKeywordDrivenExemplo.robot
└── Resource.robot
├── ExemploFakerLibrary
├── TesteExemploFakerBrasileiro.robot
└── TestCaseExemploFakerLibrary.robot
├── ExemploSOAPTesting
├── TestSOAPTesting.robot
├── consultaProcesso_envio.xml
├── MyCustomSudsLibrary
│ ├── utils.py
│ ├── monkeypatches.py
│ ├── factory.py
│ ├── soaplogging.py
│ ├── proxy.py
│ ├── clientmanagement.py
│ ├── wsse.py
│ ├── MySudsLibrary.py
│ └── options.py
├── ResourceSOAPTesting_withXMLinput.robot
└── ResourceSOAPTesting.robot
├── QArentenaBlogTest
├── TestsBlog.robot
└── ResourceBlog.robot
├── ExemploDateTimeRobot
└── Exemplo_DateTime.robot
├── SuiteCadastroQANinja
├── TestCasesCadastroQANinja.robot
└── ResourceCadastroQANinja.robot
├── ExemploAPI
├── tests
│ └── TestCasesAPIRequests.robot
└── resources
│ ├── BDDImplementation.robot
│ └── Steps.robot
├── ExemploDataDriven
├── TestCasesDataDrivenExemplo.robot
├── Resource.robot
└── TestsCasesExemploMaisDeUmTemplate.robot
├── Exemplo Imap Library
├── exemplo_keyword_usando_ImapLibrary.txt
└── CustomImapLibrary.py
├── ExemploBrowser
└── browser_example.robot
├── language-robot-framework
└── grammars
│ └── robottxt.cson
└── RabbitMQ
├── ResourceRabbitMQ.robot
└── RabbitMqCustom.py
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-tactile
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #robotframework
2 | *.html
3 | *.log
4 | *output.xml
5 | *.png
6 | *.pyc
7 | *.zip
8 | playwright-log.txt
9 | Results/
--------------------------------------------------------------------------------
/ExemploAPI_ServeRest/requirements.txt:
--------------------------------------------------------------------------------
1 | robotframework==3.2.2
2 | robotframework-faker==5.0.0
3 | robotframework-requests==0.8.0
4 |
--------------------------------------------------------------------------------
/ExemploSikuli/img/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mayribeirofernandes/testesrobotframework/HEAD/ExemploSikuli/img/close.png
--------------------------------------------------------------------------------
/ExemploAutoIt/SEALsScript.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mayribeirofernandes/testesrobotframework/HEAD/ExemploAutoIt/SEALsScript.zip
--------------------------------------------------------------------------------
/ExemploSikuli/img/helloword.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mayribeirofernandes/testesrobotframework/HEAD/ExemploSikuli/img/helloword.png
--------------------------------------------------------------------------------
/ExemploSikuli/img/notepad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mayribeirofernandes/testesrobotframework/HEAD/ExemploSikuli/img/notepad.png
--------------------------------------------------------------------------------
/ExemploSikuli/img/notepad_workspace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mayribeirofernandes/testesrobotframework/HEAD/ExemploSikuli/img/notepad_workspace.png
--------------------------------------------------------------------------------
/ExemploSikuli/img/windows_start_menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mayribeirofernandes/testesrobotframework/HEAD/ExemploSikuli/img/windows_start_menu.png
--------------------------------------------------------------------------------
/ExemploSikuli/ExemploExecucaoRobotSikuli.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mayribeirofernandes/testesrobotframework/HEAD/ExemploSikuli/ExemploExecucaoRobotSikuli.mp4
--------------------------------------------------------------------------------
/ExemploLibraryXML/TestXML.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Resource ResourceXML.robot
3 |
4 | *** Test Case ***
5 | Teste de manipulação de XML
6 | Manipular e conferir XML
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Bem-vindo Robotizadores
2 |
3 | Neste repositório deixarei os exemplos que citarei no Blog Robotizando Testes.
4 |
5 | Acesse!(https://robotizandotestes.blogspot.com.br)
--------------------------------------------------------------------------------
/Demos/DemoAPI/BDDpt-br.robot:
--------------------------------------------------------------------------------
1 | *** Keywords ***
2 | Dado ${keyword}
3 | Run keyword ${keyword}
4 |
5 | Quando ${keyword}
6 | Run keyword ${keyword}
7 |
8 | Então ${keyword}
9 | Run keyword ${keyword}
10 |
11 | E ${keyword}
12 | Run keyword ${keyword}
13 |
--------------------------------------------------------------------------------
/ExemploBDD/BDDpt-br.robot:
--------------------------------------------------------------------------------
1 | *** Keywords ***
2 | Dado ${keyword}
3 | Run keyword ${keyword}
4 |
5 | Quando ${keyword}
6 | Run keyword ${keyword}
7 |
8 | Então ${keyword}
9 | Run keyword ${keyword}
10 |
11 | E ${keyword}
12 | Run keyword ${keyword}
--------------------------------------------------------------------------------
/Demos/DemoWeb/resources/BDDpt-br.robot:
--------------------------------------------------------------------------------
1 | *** Keywords ***
2 | Dado ${keyword}
3 | Run keyword ${keyword}
4 |
5 | Quando ${keyword}
6 | Run keyword ${keyword}
7 |
8 | Então ${keyword}
9 | Run keyword ${keyword}
10 |
11 | E ${keyword}
12 | Run keyword ${keyword}
13 |
--------------------------------------------------------------------------------
/SuitePalestraGUTS/SuiteExemploAPI/BDDpt-br.robot:
--------------------------------------------------------------------------------
1 | *** Keywords ***
2 | Dado ${keyword}
3 | Run keyword ${keyword}
4 |
5 | Quando ${keyword}
6 | Run keyword ${keyword}
7 |
8 | Então ${keyword}
9 | Run keyword ${keyword}
10 |
11 | E ${keyword}
12 | Run keyword ${keyword}
--------------------------------------------------------------------------------
/ExemploPabot/TestCaseLoginChrome.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Resource ./Resource_steps_login.robot
3 | Suite Teardown Close browser
4 |
5 | *** Test Cases ***
6 | Cenário: Login com sucesso
7 | Dado que estou na tela de login no Chrome
8 | Quando realizo o login
9 | Então devo visualizar a mensagem "You logged into a secure area!"
10 |
--------------------------------------------------------------------------------
/ExemploPabot/TestCaseLoginFirefox.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Resource ./Resource_steps_login.robot
3 | Suite Teardown Close browser
4 |
5 | *** Test Cases ***
6 | Cenário: Login com sucesso
7 | Dado que estou na tela de login no Firefox
8 | Quando realizo o login
9 | Então devo visualizar a mensagem "You logged into a secure area!"
10 |
--------------------------------------------------------------------------------
/ExemploMyCustomLibrary/libraries/decode64.py:
--------------------------------------------------------------------------------
1 | import base64
2 |
3 | def decode_64_to_string(stringEncoded):
4 | print("Deconding [%s] to string." % stringEncoded)
5 |
6 | if not stringEncoded.endswith("=="):
7 | stringEncoded = stringEncoded + "=="
8 |
9 | stringDecoded = base64.b64decode(stringEncoded)
10 |
11 | return stringDecoded.decode('UTF-8')
12 |
--------------------------------------------------------------------------------
/ExemploSelenium/TestCasesKeywordDrivenExemplo.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Resource Resource.robot
3 | Suite Teardown Fechar Navegador
4 |
5 | *** Test Case ***
6 | Validar acesso ao blog robotizandotestes
7 | Acessar blog robotizandotestes
8 |
9 | Validar pesquisa de postagens
10 | Pesquisar a postagem "season premiere"
11 | Clicar no post "Season Premiere: Introdução ao Robot Framework" encontrado
--------------------------------------------------------------------------------
/ExemploFakerLibrary/TesteExemploFakerBrasileiro.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Documentation Faker com dados brasileiros
3 | Library FakerLibrary locale=pt_BR
4 |
5 | *** Test Cases ***
6 | Teste dados fakes BRASILEIROS
7 | ${CPF} FakerLibrary.cpf
8 | ${NOME} FakerLibrary.name
9 | ${CIDADE} FakerLibrary.city
10 | ${CEP} FakerLibrary.postcode
11 | ${ESTADO} FakerLibrary.state
12 |
--------------------------------------------------------------------------------
/ExemploSOAPTesting/TestSOAPTesting.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Resource ResourceSOAPTesting.robot
3 | Resource ResourceSOAPTesting_withXMLinput.robot
4 |
5 | *** Test Case ***
6 | Teste SOAP preenchendo campo a campo da requisição
7 | Enviar requisição SOAP preenchendo campo a campo da requisição
8 |
9 | Teste SOAP enviando um arquivo XML na requisição
10 | Enviar requisição SOAP enviando arquivo XML de input
11 |
--------------------------------------------------------------------------------
/ExemploAPI_ServeRest/README.md:
--------------------------------------------------------------------------------
1 | ## Testes de API com Robot Framework utilizando a nova versão da RequestsLibrary [0.8.0] e a API de estudos ServeRest
2 |
3 | As *keywords* tradicionais de *Request* estão sendo substituídas, leia sobre isso na documentação da [RequestsLibrary](https://marketsquare.github.io/robotframework-requests/doc/RequestsLibrary.html)
4 |
5 | Para conhecer a API pública de estudos **ServeRest** que utilizei para os testes [clique aqui](https://serverest.dev/).
6 |
--------------------------------------------------------------------------------
/ExemploPabot/Resource_steps_login.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library SeleniumLibrary
3 |
4 | *** Variables ***
5 | ${url} https://the-internet.herokuapp.com/login
6 |
7 | *** Keywords ***
8 | Dado que estou na tela de login no ${browser}
9 | open browser ${url} ${browser}
10 |
11 | Quando realizo o login
12 | input text id=username tomsmith
13 | input text id=password SuperSecretPassword!
14 | click button Login
15 |
16 | Então devo visualizar a mensagem "${mensagem}"
17 | element text should be id=flash You logged into a secure area!\n×
18 |
--------------------------------------------------------------------------------
/ExemploSOAPTesting/consultaProcesso_envio.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PGMBH
6 | 12345678
7 | 50224418220178130024
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/QArentenaBlogTest/TestsBlog.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Resource ResourceBlog.robot
3 | Test Setup Acessar página inicial do blog
4 | Test Teardown Fechar Navegador
5 |
6 |
7 | *** Test Cases ***
8 | Caso de Teste 01: Fazer pesquisa de um post
9 | Pesquisar por um post com "Season Premiere: Introdução ao Robot Framework"
10 | Conferir mensagem de pesquisa por "Season Premiere: Introdução ao Robot Framework"
11 |
12 | Caso de Teste 02: Ler um post
13 | Acessar o post "Season Premiere: Introdução ao Robot Framework"
14 | Conferir se a imagem do robô aparece
15 | Conferir se o texto "nesse post vou apresentar-lhes o astro deste blog" aparece
16 |
--------------------------------------------------------------------------------
/ExemploLibraryXML/xmlBaseExemplo.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ID_ANTES
6 | 12345678
7 | 19000101000000
8 | false
9 | true
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/SuitePalestraGUTS/SuiteExemploWEB/TestCasesCadastroQANinja.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Resource ResourceCadastroQANinja.robot
3 | Test Teardown Close Browser
4 |
5 | *** Test Cases ***
6 | Validar Cadastro de Usuário: Email Válido
7 | Acessar Página Principal
8 | Clicar em Cadastro
9 | Inserir Nome Completo
10 | Inserir Email Válido
11 | Inserir Senha
12 | Submeter Cadastro
13 | Conferir Mensagem de Boas Vindas
14 |
15 | Validar Cadastro de Usuário: Email Inválido
16 | Acessar Página Principal
17 | Clicar em Cadastro
18 | Inserir Nome Completo
19 | Inserir Email Inválido
20 | Inserir Senha
21 | Submeter Cadastro
22 | Conferir Mensagem de Alerta de Email Inválido
--------------------------------------------------------------------------------
/ExemploBDD/TestCasesBDDExemplo.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Resource ResourceBDD.robot
3 | Resource BDDpt-br.robot
4 | Suite Teardown Fechar Navegador
5 |
6 | *** Test Cases ***
7 | Cenário 01: Pesquisar postagem Season Premiere
8 | Dado que esteja na tela HOME do blog robotizando testes
9 | Quando pesquisar pela palavra "introdução"
10 | Então a postagem "Season Premiere: Introdução ao Robot Framework" deve ser listada no resultado da pesquisa
11 |
12 | Cenário 02: Ler postagem Season Premiere
13 | Dado que esteja na tela de resultado da pesquisa pela postagem "Season Premiere: Introdução ao Robot Framework"
14 | Quando clicar no link da postagem
15 | Então a tela da postagem "Season Premiere: Introdução ao Robot Framework" deve ser mostrada
--------------------------------------------------------------------------------
/Demos/DemoWeb/testes/TestCasesBDDExemplo.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Resource ../resources/ResourceBDD.robot
3 | Resource ../resources/BDDpt-br.robot
4 | Suite Teardown Fechar Navegador
5 |
6 | *** Test Cases ***
7 | Cenário 01: Pesquisar postagem Season Premiere
8 | Dado que esteja na tela HOME do blog robotizando testes
9 | Quando pesquisar pela palavra "introdução ao robot framework"
10 | Então a postagem "Season Premiere: Introdução ao Robot Framework" deve ser listada no resultado da pesquisa
11 |
12 | Cenário 02: Ler postagem Season Premiere
13 | Dado que esteja na tela de resultado da pesquisa pela postagem "Season Premiere: Introdução ao Robot Framework"
14 | Quando clicar no link da postagem
15 | Então a tela da postagem "Season Premiere: Introdução ao Robot Framework" deve ser mostrada
16 |
--------------------------------------------------------------------------------
/ExemploDateTimeRobot/Exemplo_DateTime.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library DateTime
3 |
4 | *** Variable ***
5 | ${DATA} 2018-01-16
6 |
7 | *** Test Cases ***
8 | Teste Operações com Datas
9 | ####Pegando a data de hoje e convertendo para formato yyyy-mm-dd
10 | ${TODAY} Get Current Date result_format=%Y-%m-%d
11 | ${DATA} Convert Date ${DATA} result_format=%Y-%m-%d
12 |
13 | ####Fazendo o cálculo
14 | ${RESULT} Subtract Date From Date ${TODAY} ${DATA}
15 | ${MONTHS} Evaluate ${RESULT}/60/60/24/30
16 |
17 | ####Formatando para ficar no formato dd-mm-yyyy
18 | ${DATA} Convert Date ${DATA} result_format=%d-%m-%Y
19 | ${TODAY} Convert Date ${TODAY} result_format=%d-%m-%Y
20 | Log Entre ${TODAY} e ${DATA} existem ${MONTHS} meses.
21 |
--------------------------------------------------------------------------------
/SuiteCadastroQANinja/TestCasesCadastroQANinja.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Resource ResourceCadastroQANinja.robot
3 | Test Teardown Close Browser
4 |
5 | *** Test Cases ***
6 | Validar Acesso ao Site QA Ninja
7 | Acessar Página Principal
8 |
9 | Validar Acesso à Página de Cadastro
10 | Acessar Página Principal
11 | Clicar em Cadastro
12 |
13 | Validar Cadastro de Usuário: Email Válido
14 | Acessar Página Principal
15 | Clicar em Cadastro
16 | Inserir Nome Completo
17 | Inserir Email Válido
18 | Inserir Senha
19 | Submeter Cadastro
20 | Conferir Mensagem de Boas Vindas
21 |
22 | Validar Cadastro de Usuário: Email Inválido
23 | Acessar Página Principal
24 | Clicar em Cadastro
25 | Inserir Nome Completo
26 | Inserir Email Inválido
27 | Inserir Senha
28 | Submeter Cadastro
29 | Conferir Mensagem de Alerta de Email Inválido
--------------------------------------------------------------------------------
/ExemploAPI/tests/TestCasesAPIRequests.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Documentation Suíte de Exemplo de testes API com o Robot Framework
3 | Resource ../resources/BDDImplementation.robot
4 |
5 | *** Test Case ***
6 | Cenário 01: Consulta de endereço existente
7 | [Tags] jenkins
8 | Dado que esteja conectado no webservice de consultas de CEP
9 | Quando o usuário consultar o CEP "88056-000"
10 | Então deve ser mostrado o endereço "Avenida Luiz Boiteux Piazza"
11 | E deve ser mostrado o bairro "Cachoeira do Bom Jesus"
12 | E deve ser mostrada a cidade "Florianópolis"
13 | E deve ser mostrada a UF "SC"
14 | E deve ser mostrado o CEP "88056000"
15 |
16 | Cenário 02: Consulta de endereço inexistente
17 | Dado que esteja conectado no webservice de consultas de CEP
18 | Quando o usuário consultar o CEP "99999-999"
19 | Então a mensagem "CEP INVÁLIDO" deve ser retornada
20 |
--------------------------------------------------------------------------------
/ExemploMyCustomLibrary/TestCaseExemploMyCustomLibrary.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Documentation Exemplo de uso de uma Library personalizada e criada por mim em Python
3 | ... Essa library irá decodificar uma string em base64 para UTF-8
4 | Library ./libraries/decode64.py
5 |
6 | *** Test Cases ***
7 | Teste da minha custom library
8 | Decodificar o texto "TWluaGEgZnJhc2UgZGUgdGVzdGUh"
9 | Conferir se o texto decodificado é "Minha frase de teste!"
10 |
11 | *** Keywords ***
12 | Decodificar o texto "${TEXTO_CODIFICADO_BASE64}"
13 | ${TEXTO_DECODIFICADO} decode 64 to string ${TEXTO_CODIFICADO_BASE64}
14 | Set Test Variable ${TEXTO_DECODIFICADO}
15 | Log Frase codificada: ${TEXTO_CODIFICADO_BASE64} -- Frase decodificada: ${TEXTO_DECODIFICADO}
16 |
17 | Conferir se o texto decodificado é "${FRASE_ESPERADA}"
18 | Should Be Equal ${TEXTO_DECODIFICADO} ${FRASE_ESPERADA}
19 |
--------------------------------------------------------------------------------
/SuitePalestraGUTS/SuiteExemploAPI/TestCasesAPIRequests.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Documentation Suíte de Exemplo de testes API com o Robot Framework
3 | Resource BDDpt-br.robot
4 | Resource Resource.robot
5 |
6 | *** Test Case ***
7 | Cenário 01: Consulta de endereço existente
8 | Dado que esteja conectado no webservice de consultas de CEP
9 | Quando o usuário consultar o CEP "88056-000"
10 | Então deve ser mostrado o endereço "Avenida Luiz Boiteux Piazza"
11 | E deve ser mostrado o bairro "Cachoeira do Bom Jesus"
12 | E deve ser mostrada a cidade "Florianópolis"
13 | E deve ser mostrada a UF "SC"
14 | E deve ser mostrado o CEP "88056000"
15 |
16 | Cenário 02: Consulta de endereço inexistente
17 | Dado que esteja conectado no webservice de consultas de CEP
18 | Quando o usuário consultar o CEP "99999-999"
19 | Então nenhum dado deve ser mostrado para o CEP "99999999"
--------------------------------------------------------------------------------
/ExemploDataDriven/TestCasesDataDrivenExemplo.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Resource Resource.robot
3 | Suite Setup Acessar blog robotizandotestes
4 | Suite Teardown Fechar Navegador
5 | Test Template Validar pesquisa de postagens
6 |
7 | *** Test Case *** Busca Título do Post
8 |
9 | Pesquisar Post Premiere introdução Season Premiere: Introdução ao Robot Framework
10 | Pesquisar Post Editores Ep.01 visual code Season Editores - Ep. 02: Visual Studio Code
11 | Pesquisar Post Tutoriais Ep.01 windows Season Tutoriais - Ep. 01: Instalando o Robot Framework (Windows)
12 |
13 | *** Keyword ***
14 | Validar pesquisa de postagens
15 | [Arguments] ${BUSCA} ${TITULO_POSTAGEM}
16 | Pesquisar a postagem pela palavra "${BUSCA}"
17 | Verificar resultado da pesquisa ${TITULO_POSTAGEM}
18 | Clicar no post encontrado
19 | Verificar tela da postagem ${TITULO_POSTAGEM}
--------------------------------------------------------------------------------
/ExemploSikuli/TesteSikuli.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Documentation Sikuli Library Demo
3 | Test Setup Carrega diretório de imagens
4 | Test Teardown Stop Remote Server
5 | Library SikuliLibrary
6 |
7 | *** Variables ***
8 | #As imagens da pasta img devem estar de acordo com a interface do seu PC!!!! Tire os prints necessários!
9 | ${IMAGE_DIR} ${CURDIR}\\img
10 |
11 | *** Test Cases ***
12 | Windows Notepad Hello World
13 | Abre o menu inicial do windows
14 | Abre o notepad++
15 | Digita "Hello Word"
16 | Fecha o notepad++
17 |
18 | *** Keywords ***
19 | Carrega diretório de imagens
20 | Add Image Path ${IMAGE_DIR}
21 |
22 | Abre o menu inicial do windows
23 | Click windows_start_menu.png
24 |
25 | Abre o notepad++
26 | Click notepad.png
27 |
28 | Digita "${TEXTO}"
29 | Input Text notepad_workspace.png ${TEXTO}
30 | Screen Should Contain helloword.png
31 |
32 | Fecha o notepad++
33 | Click close.png
--------------------------------------------------------------------------------
/ExemploAPI/resources/BDDImplementation.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Resource Steps.robot
3 |
4 | *** Keywords ***
5 | #### DADO
6 | Dado que esteja conectado no webservice de consultas de CEP
7 | Conecta ao WebService
8 |
9 | #### QUANDO
10 | Quando o usuário consultar o CEP "${CEP_CONSULTADO}"
11 | Realiza requisição do CEP ${CEP_CONSULTADO}
12 |
13 | #### ENTÃO
14 | Então deve ser mostrado o endereço "${ENDERECO}"
15 | Confere o status code 200
16 | Confere endereço do CEP ${ENDERECO}
17 |
18 | E deve ser mostrado o bairro "${BAIRRO}"
19 | Confere bairro do CEP ${BAIRRO}
20 |
21 | E deve ser mostrada a cidade "${CIDADE}"
22 | Confere cidade do CEP ${CIDADE}
23 |
24 | E deve ser mostrada a UF "${UF}"
25 | Confere UF do CEP ${UF}
26 |
27 | E deve ser mostrado o CEP "${CEP}"
28 | Confere CEP ${CEP}
29 |
30 | Então a mensagem "${ERROR_MSG}" deve ser retornada
31 | Confere o status code 200
32 | Confere Mensagem de Erro ${ERROR_MSG}
33 |
--------------------------------------------------------------------------------
/Exemplo Imap Library/exemplo_keyword_usando_ImapLibrary.txt:
--------------------------------------------------------------------------------
1 | ----> Fiz uns ajustes no código fonte da library, então usei ela customizada no projeto:
2 |
3 | *** Settings ***
4 | Library CustomImapLibrary.py
5 |
6 | ----> Meu código que funcionava (é um código de 2 anos atrás tá):
7 |
8 | Confere envio de e-mail de alerta de saldo
9 | Open Mailbox host=${IMAP.host} port=${IMAP.port} user=${IMAP.user} password=${IMAP.password}
10 | ${EMAIL_INDEX} Wait For Email sender=blablablabla@gmail.com status=UNSEEN timeout=30
11 | ${BODY} Get Email Body ${EMAIL_INDEX}
12 | Delete Email ${EMAIL_INDEX}
13 | ${BODY} Decode Email Body ${BODY}
14 | Should Contain ${BODY} Cliente: Cliente Teste - Consultas Utilizadas: 1
15 | Close Mailbox
16 |
17 |
18 | ---> tinha a keyword de limpar a caixa no setup do teste:
19 |
20 | Limpar Email
21 | Open Mailbox host=${IMAP.host} port=${IMAP.port} user=${IMAP.user} password=${IMAP.password}
22 | Delete All Emails
23 | Close Mailbox
--------------------------------------------------------------------------------
/ExemploAutoIt/testeAutoIt.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library AutoItLibrary
3 |
4 | *** Test Cases ***
5 | Joaninha
6 | Abrir Joaninha
7 | Digitar Defeito
8 |
9 | *** Keywords ***
10 | Abrir Joaninha
11 | # O diretório desse executavel, configurei nas variáveis de ambiente do windows
12 | Run SEALsScript.exe
13 | Win Wait WindowTitle=SEAL´s Scripts
14 |
15 | Digitar Defeito
16 | Control Focus strTitle=SEAL´s Scripts strText=${EMPTY} strControl=TMemo4
17 | Send Meu texto para o campo Descrição do Defeito
18 | Control Focus strTitle=SEAL´s Scripts strText=${EMPTY} strControl=TEdit1
19 | Send Meu texto para o campo Aplicativo
20 | Control Focus strTitle=SEAL´s Scripts strText=${EMPTY} strControl=TMemo2
21 | Send Meu texto para o campo Procedimento do Teste
22 | Control Focus strTitle=SEAL´s Scripts strText=${EMPTY} strControl=TMemo1
23 | Send Meu texto para o campo Evidências
24 | Control Click strTitle=SEAL´s Scripts strText=Copiar strControl=TBitBtn2
25 |
--------------------------------------------------------------------------------
/ExemploBrowser/browser_example.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library Browser
3 |
4 |
5 | *** Test Cases ***
6 | Exemplo com a library Browser
7 | Abrindo uma tab no navegador no site http://www.google.com.br
8 | Fazer pesquisa com a frase robot framework
9 | Verificar se aparece o header do Robot Framework
10 |
11 |
12 | *** Keywords ***
13 | Abrindo uma tab no navegador no site
14 | [Arguments] ${url}
15 | # Por default o browser será headless, aqui optamos por ver o browser
16 | New Browser headless=False
17 |
18 | # Quero um contexto de teste que GRAVE as execuções
19 | New Context recordVideo={'dir': '${OUTPUT_DIR}/video'}
20 |
21 | # Abro uma ABA no navegador com a URL desejada
22 | New Page url=${url}
23 |
24 | Fazer pesquisa com a frase
25 | [Arguments] ${frase_pesquisa}
26 | Fill Text css=input[name=q] ${frase_pesquisa}
27 | Click :nth-match(:text("Pesquisa Google"), 2)
28 |
29 | Verificar se aparece o header do Robot Framework
30 | # As asserções são feitas com Getters, onde passamos o locator +
31 | # a condição + o valor esperado tudo na mesma linha, nessa ordem
32 | Get Text h2 > span == Robot Framework
33 |
--------------------------------------------------------------------------------
/Demos/DemoAPI/TestCasesAPIRequests.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Documentation Suíte de Exemplo de testes API com o Robot Framework
3 | Resource BDDpt-br.robot
4 | Resource Resource.robot
5 |
6 | *** Test Case ***
7 | Cenário 01: Consulta de endereço existente
8 | Dado que esteja conectado no webservice de consultas de CEP
9 | Quando o usuário consultar o CEP "88056-000"
10 | Então deve ser mostrado o endereço "Avenida Luiz Boiteux Piazza"
11 | E deve ser mostrado o bairro "Cachoeira do Bom Jesus"
12 | E deve ser mostrada a cidade "Florianópolis"
13 | E deve ser mostrada a UF "SC"
14 | E deve ser mostrado o CEP "88056000"
15 |
16 | ##Cenário 02 Depreciado em 12/04/2019 devido atualização na API
17 | # Cenário 02: Consulta de endereço inexistente
18 | # Dado que esteja conectado no webservice de consultas de CEP
19 | # Quando o usuário consultar o CEP "99999-999"
20 | # Então nenhum dado deve ser mostrado para o CEP "99999999"
21 |
22 | Cenário 03: Consulta de endereço inexistente
23 | Dado que esteja conectado no webservice de consultas de CEP
24 | Quando o usuário consultar o CEP "99999-999"
25 | Então a mensagem de erro "CEP INVÁLIDO" deve ser retornada
26 |
--------------------------------------------------------------------------------
/ExemploSelenium/Resource.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library SeleniumLibrary
3 |
4 | *** Variable ***
5 | ${BROWSER} firefox
6 | ${URL} https://robotizandotestes.blogspot.com.br/
7 | ${CABEÇALHO} Header1
8 | ${BOTAO_LUPA} css=.search-expand.touch-icon-button
9 | ${CAMPO_PESQUISAR} css=.search-input>input
10 | ${BOTAO_PESQUISAR} css=.search-action.flat-button
11 | ${LINK_POST} xpath=.//*[@id='Blog1']/div[1]/article/div/div/h3/a
12 | ${TITULO_POST} xpath=.//*[@id='Blog1']/div/article/div[1]/div/h3
13 |
14 | *** Keywords ***
15 | Acessar blog robotizandotestes
16 | Open Browser ${URL} ${BROWSER}
17 | Wait Until Element Is Visible ${CABEÇALHO}
18 | Title Should Be Robotizando Testes
19 |
20 | Pesquisar a postagem "${PESQUISA}"
21 | Click Element ${BOTAO_LUPA}
22 | Input Text ${CAMPO_PESQUISAR} ${PESQUISA}
23 | Click Element ${BOTAO_PESQUISAR}
24 | Wait Until Element Is Visible ${LINK_POST}
25 |
26 | Clicar no post "${TITULO_POST_DESC}" encontrado
27 | Click Element ${LINK_POST}
28 | Wait Until Element Is Visible ${TITULO_POST}
29 | Title Should Be ${TITULO_POST_DESC}
30 |
31 | Fechar Navegador
32 | Close Browser
33 |
--------------------------------------------------------------------------------
/ExemploSOAPTesting/MyCustomSudsLibrary/utils.py:
--------------------------------------------------------------------------------
1 | # Copyright 2013 Kevin Ormbrek
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | from robot import utils
16 |
17 |
18 | # assumed that no WSDL will have a service or port named "1", etc.
19 | def parse_index(value):
20 | try:
21 | return int(value)
22 | except (ValueError, TypeError):
23 | return value
24 |
25 |
26 | def to_bool(item):
27 | if isinstance(item, str):
28 | if utils.eq(item, 'True'):
29 | return True
30 | if utils.eq(item, 'False'):
31 | return False
32 | return bool(item)
33 |
34 |
35 | def format_robot_time(timestr):
36 | secs = utils.timestr_to_secs(timestr)
37 | return utils.secs_to_timestr(secs)
38 |
--------------------------------------------------------------------------------
/ExemploSOAPTesting/ResourceSOAPTesting_withXMLinput.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | ### Para rodar esse exemplo foi necessária uma correção na Library SudsLibrary
3 | ### Issue: https://github.com/ombre42/robotframework-sudslibrary/issues/32
4 | ### Por isso uso a minha library customizada MySudsLibrary.py, que já fiz a correção
5 | Library ./MyCustomSudsLibrary/MySudsLibrary.py
6 | Library OperatingSystem
7 |
8 | *** Variables ***
9 | ### Você vai precisar o WSDL do seu webservice/SOAP Client destino
10 | ${WSDL_URL} http://localhost:8077/servico-intercomunicacao-2.2.2/intercomunicacao?wsdl
11 |
12 | *** Keywords ***
13 | Enviar requisição SOAP enviando arquivo XML de input
14 | ### Abra a conexão com o SOAP Cliente destino
15 | MySudsLibrary.Create Soap Client ${WSDL_URL}
16 |
17 | ### Pegue um XML no diretório
18 | ${MESSAGE} Get File consultaProcesso_envio.xml
19 |
20 | ### Transforme ele em um Raw Message para ser enviado na requisição
21 | ${MESSAGE} MySudsLibrary.Create Raw Soap Message ${MESSAGE}
22 | Log Mensagem enviada:\n${MESSAGE}
23 |
24 | ### Faça a requisição SOAP
25 | MySudsLibrary.Call Soap Method consultarProcesso ${MESSAGE}
26 |
27 | ### Pegue o XML recebido
28 | ${RESPOSTA_XML} MySudsLibrary.Get Last Received
29 | Log Mensagem Recebida:\n${RESPOSTA_XML}
30 |
--------------------------------------------------------------------------------
/ExemploDataDriven/Resource.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library SeleniumLibrary
3 |
4 | *** Variable ***
5 | ${BROWSER} firefox
6 | ${URL} https://robotizandotestes.blogspot.com.br/
7 | ${CABEÇALHO} Header1
8 | ${BOTAO_LUPA} css=.search-expand.touch-icon-button
9 | ${CAMPO_PESQUISAR} css=.search-input>input
10 | ${BOTAO_PESQUISAR} css=.search-action.flat-button
11 | ${LINK_POST} xpath=.//*[@id='Blog1']/div[1]/article/div/div/h3/a
12 | ${TITULO} xpath=.//*[@id='Blog1']/div/article/div[1]/div/h3
13 |
14 | *** Keywords ***
15 | Acessar blog robotizandotestes
16 | Open Browser ${URL} ${BROWSER}
17 | Wait Until Element Is Visible ${CABEÇALHO}
18 | Title Should Be Robotizando Testes
19 |
20 | Pesquisar a postagem pela palavra "${BUSCA}"
21 | Click Element ${BOTAO_LUPA}
22 | Input Text ${CAMPO_PESQUISAR} ${BUSCA}
23 | Click Element ${BOTAO_PESQUISAR}
24 | Wait Until Element Is Visible ${LINK_POST}
25 |
26 | Verificar resultado da pesquisa
27 | [Arguments] ${TITULO_POSTAGEM}
28 | Page Should Contain ${TITULO_POSTAGEM}
29 |
30 | Clicar no post encontrado
31 | Click Element ${LINK_POST}
32 |
33 | Verificar tela da postagem
34 | [Arguments] ${TITULO_POSTAGEM}
35 | Wait Until Element Is Visible ${TITULO}
36 | Title Should Be ${TITULO_POSTAGEM}
37 |
38 | Fechar Navegador
39 | Close Browser
--------------------------------------------------------------------------------
/ExemploSOAPTesting/ResourceSOAPTesting.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | ### Instale a library: pip install robotframework-sudslibrary-aljcalandra
3 | Library SudsLibrary
4 |
5 | *** Variables ***
6 | ### Você vai precisar o WSDL do seu webservice/SOAP Client destino
7 | ${WSDL_URL} http://localhost:8077/servico-intercomunicacao-2.2.2/intercomunicacao?wsdl
8 |
9 | ### Você deverá montar um dicionário com os dados que precisa passar na chamada do método
10 | ### Esse exemplo abaixo são os campos obrigatórios do método
11 | ### Esses campos são os mesmos do arquivo consultaProcesso_envio.xml
12 | &{MSG_ENVIO} idConsultante=PGMBH senhaConsultante=12345678 numeroProcesso=50224418220178130024
13 |
14 | *** Keywords ***
15 | Enviar requisição SOAP preenchendo campo a campo da requisição
16 | ### Abra a conexão com o SOAP Cliente destino
17 | SudsLibrary.Create Soap Client ${WSDL_URL}
18 |
19 | ### Chame o método passando campo a campo da requisição
20 | ### A resposta será armazenada na variável ${RESPOSTA_XML}
21 | SudsLibrary.Call Soap Method consultarProcesso
22 | ... ${MSG_ENVIO.idConsultante}
23 | ... ${MSG_ENVIO.senhaConsultante}
24 | ... ${MSG_ENVIO.numeroProcesso}
25 |
26 | ### Pegue o XML recebido
27 | ${RESPOSTA_XML} SudsLibrary.Get Last Received
28 | Log Mensagem Recebida:\n${RESPOSTA_XML}
29 |
--------------------------------------------------------------------------------
/QArentenaBlogTest/ResourceBlog.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library SeleniumLibrary
3 |
4 | *** Variables ***
5 | ${URL} https://robotizandotestes.blogspot.com/
6 | ${BROWSER} chrome
7 | ${BTN_PESQUISA} css=.search-expand.touch-icon-button
8 | ${INPUT_PESQUISA} name=q
9 | ${SUBMIT_PESQUISA} css=.search-action.flat-button
10 | ${LINK_POST} xpath=//a[contains(text(),'Season Premiere: Introdução ao Robot Framework')]
11 | ${IMG_ROBO} xpath=//img[contains(@src,'if_Robot_18_385830_grande')]
12 |
13 | *** Keywords ***
14 | Acessar página inicial do blog
15 | Open Browser ${URL} ${BROWSER}
16 | Title Should Be Robotizando Testes
17 |
18 | Fechar Navegador
19 | Close Browser
20 |
21 | Pesquisar por um post com "${TEXTO_PESQUISA}"
22 | Wait Until Element Is Visible ${BTN_PESQUISA}
23 | Click Button ${BTN_PESQUISA}
24 | Input Text ${INPUT_PESQUISA} ${TEXTO_PESQUISA}
25 | Click Button ${SUBMIT_PESQUISA}
26 |
27 | Conferir mensagem de pesquisa por "${TEXTO_PESQUISA}"
28 | Page Should Contain Mostrando postagens que correspondem à pesquisa por ${TEXTO_PESQUISA}
29 |
30 | Acessar o post "${POST}"
31 | Pesquisar por um post com "${POST}"
32 | Click Element ${LINK_POST}
33 | Wait Until Page Contains O que é Robot Framework?
34 |
35 | Conferir se a imagem do robô aparece
36 | Page Should Contain Image ${IMG_ROBO}
37 |
38 | Conferir se o texto "${TEXTO_DESEJADO}" aparece
39 | Page Should Contain ${TEXTO_DESEJADO}
40 |
--------------------------------------------------------------------------------
/Demos/DemoWeb/resources/ResourceBDD.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library SeleniumLibrary
3 |
4 | *** Variable ***
5 | ${BROWSER} chrome
6 | ${URL} https://robotizandotestes.blogspot.com.br/
7 | ${CABEÇALHO} id=Header1
8 | ${BOTAO_LUPA} css=.search-expand.touch-icon-button
9 | ${CAMPO_PESQUISAR} css=.search-input>input
10 | ${BOTAO_PESQUISAR} css=.search-action.flat-button
11 | ${LINK_POST} xpath=.//*[@id='Blog1']/div[1]/article/div/div/h3/a
12 | ${TITULO} xpath=.//*[@id='Blog1']/div/article/div[1]/div/h3
13 |
14 | *** Keywords ***
15 | #### DADO
16 | Que esteja na tela HOME do blog robotizando testes
17 | Open Browser ${URL} ${BROWSER}
18 | Wait Until Element Is Visible ${CABEÇALHO}
19 | Title Should Be Robotizando Testes
20 |
21 | Que esteja na tela de resultado da pesquisa pela postagem "${TITULO_POSTAGEM}"
22 | Page Should Contain ${TITULO_POSTAGEM}
23 |
24 | #### QUANDO
25 | Pesquisar pela palavra "${BUSCA}"
26 | Click Element ${BOTAO_LUPA}
27 | Input Text ${CAMPO_PESQUISAR} ${BUSCA}
28 | Sleep 2s
29 | Click Element ${BOTAO_PESQUISAR}
30 | Wait Until Element Is Visible ${LINK_POST}
31 |
32 | Clicar no link da postagem
33 | Click Element ${LINK_POST}
34 | Sleep 2s
35 |
36 | #### ENTÃO
37 | A postagem "${TITULO_POSTAGEM}" deve ser listada no resultado da pesquisa
38 | Page Should Contain ${TITULO_POSTAGEM}
39 |
40 | A tela da postagem "${TITULO_POSTAGEM}" deve ser mostrada
41 | Wait Until Element Is Visible ${TITULO}
42 | Title Should Be ${TITULO_POSTAGEM}
43 | Sleep 2s
44 |
45 | #### TEARDOWN
46 | Fechar Navegador
47 | Close Browser
48 |
--------------------------------------------------------------------------------
/language-robot-framework/grammars/robottxt.cson:
--------------------------------------------------------------------------------
1 | 'comment': '\n\tRobot Framework syntax highlighting for txt format.\t\n\t'
2 | 'fileTypes': [
3 | 'robot'
4 | ]
5 | 'name': 'Robot Framework'
6 | 'firstLineMatch': '\\*{3} (?i:Settings|Keywords|Variables|Test Cases) \\*{3}'
7 | 'patterns': [
8 | {
9 | 'match': '(^\\*\\*\\*.*?\\*\\*\\*)|((?<=^\\|)\\s+\\*\\*\\*.*?\\*\\*\\*)'
10 | 'name': 'string.robot.header'
11 | }
12 | {
13 | 'include': '#tag'
14 | }
15 | {
16 | 'include': '#variables'
17 | }
18 | {
19 | 'include': '#comment'
20 | }
21 | {
22 | 'begin': '^(?![ \\t\\n\\*\\|])'
23 | 'contentName': 'keyword.control.robot'
24 | 'end': '\\s{2,}|\\t|$'
25 | 'patterns': [
26 | {
27 | 'include': '#variables'
28 | }
29 | ]
30 | }
31 | {
32 | 'match': '(?:^[\\s\\t]+)(Dado|Quando|Então|E |Mas)'
33 | 'captures':
34 | '1':
35 | 'name': 'keyword.control.robot'
36 | }
37 | ]
38 | 'repository':
39 | 'variables':
40 | 'begin': '([\\$@&]{)'
41 | 'beginCaptures':
42 | '0':
43 | 'name': 'punctuation.section.embedded.begin.robot'
44 | '1':
45 | 'name': 'text.robot'
46 | 'end': '(})'
47 | 'contentName': 'variable.control.robot'
48 | 'endCaptures':
49 | '0':
50 | 'name': 'punctuation.section.embedded.end.robot'
51 | '1':
52 | 'name': 'text.robot'
53 | 'comment':
54 | 'match': '(?:^[\\s\\t]*)(#.*)$'
55 | 'captures':
56 | '1':
57 | 'name': 'comment.line.robot'
58 | 'tag':
59 | 'match': '^[\\s\\t]*(\\[.+\\])'
60 | 'captures':
61 | '0':
62 | 'name': 'entity.tag.name.robot'
63 | '1':
64 | 'name': 'text.robot'
65 | 'scopeName': 'text.robot'
66 |
--------------------------------------------------------------------------------
/ExemploAPI/resources/Steps.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library RequestsLibrary
3 | Library Collections
4 |
5 | *** Variable ***
6 | ${HOST} https://webmaniabr.com/api/1/cep
7 | ${APP_KEY} njMf2EiyQ17g6C3vLUxk1yEsWTforVqf
8 | ${APP_SECRET} EgpTuUcM93IqHY8icgR3cK6Cn4bOlkQwSlfLd6ryMjrhhwMW
9 |
10 | *** Keywords ***
11 | #### STEPS
12 | Conecta ao WebService
13 | Create Session consultaCEP ${HOST} disable_warnings=True
14 |
15 | Realiza requisição do CEP
16 | [Arguments] ${CEP_DESEJADO}
17 | ${RESPOSTA}= Get Request consultaCEP /${CEP_DESEJADO}/?app_key=${APP_KEY}&app_secret=${APP_SECRET}
18 | Log Resposta: ${RESPOSTA.text}
19 | Set Test Variable ${RESPOSTA}
20 |
21 | Confere o status code
22 | [Arguments] ${STATUS_ESPERADO}
23 | Should Be Equal As Strings ${RESPOSTA.status_code} ${STATUS_ESPERADO}
24 | Log Status Code Retornado: ${RESPOSTA.status_code} -- Status Code Esperado: ${STATUS_ESPERADO}
25 |
26 | Confere endereço do CEP
27 | [Arguments] ${ENDERECO}
28 | Dictionary Should Contain Item ${RESPOSTA.json()} endereco ${ENDERECO}
29 |
30 | Confere bairro do CEP
31 | [Arguments] ${BAIRRO}
32 | Dictionary Should Contain Item ${RESPOSTA.json()} bairro ${BAIRRO}
33 |
34 | Confere cidade do CEP
35 | [Arguments] ${CIDADE}
36 | Dictionary Should Contain Item ${RESPOSTA.json()} cidade ${CIDADE}
37 |
38 | Confere UF do CEP
39 | [Arguments] ${UF}
40 | Dictionary Should Contain Item ${RESPOSTA.json()} uf ${UF}
41 |
42 | Confere CEP
43 | [Arguments] ${CEP}
44 | Dictionary Should Contain Item ${RESPOSTA.json()} cep ${CEP}
45 |
46 | Confere Mensagem de Erro
47 | [Arguments] ${ERROR_MSG}
48 | Dictionary Should Contain Item ${RESPOSTA.json()} error ${ERROR_MSG}
49 |
--------------------------------------------------------------------------------
/ExemploBDD/ResourceBDD.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library SeleniumLibrary
3 |
4 | *** Variable ***
5 | ${BROWSER} firefox
6 | ${URL} https://robotizandotestes.blogspot.com.br/
7 | ${CABEÇALHO} Header1
8 | ${BOTAO_LUPA} css=.search-expand.touch-icon-button
9 | ${CAMPO_PESQUISAR} css=.search-input>input
10 | ${BOTAO_PESQUISAR} css=.search-action.flat-button
11 | ${LINK_POST} xpath=.//*[@id='Blog1']/div[1]/article/div/div/h3/a
12 | ${TITULO} xpath=.//*[@id='Blog1']/div/article/div[1]/div/h3
13 |
14 | *** Keywords ***
15 | #### DADO
16 | Que esteja na tela HOME do blog robotizando testes
17 | Acessar blog robotizandotestes
18 |
19 | Que esteja na tela de resultado da pesquisa pela postagem "${TITULO_POSTAGEM}"
20 | Verificar resultado da pesquisa ${TITULO_POSTAGEM}
21 |
22 | #### QUANDO
23 | Pesquisar pela palavra "${BUSCA}"
24 | Pesquisar a postagem pela palavra "${BUSCA}"
25 |
26 | Clicar no link da postagem
27 | Clicar no post encontrado
28 |
29 | #### ENTÃO
30 | A postagem "${TITULO_POSTAGEM}" deve ser listada no resultado da pesquisa
31 | Verificar resultado da pesquisa ${TITULO_POSTAGEM}
32 |
33 | A tela da postagem "${TITULO_POSTAGEM}" deve ser mostrada
34 | Verificar tela da postagem ${TITULO_POSTAGEM}
35 |
36 | #### PASSOS
37 | Acessar blog robotizandotestes
38 | Open Browser ${URL} ${BROWSER}
39 | Wait Until Element Is Visible ${CABEÇALHO}
40 | Title Should Be Robotizando Testes
41 |
42 | Pesquisar a postagem pela palavra "${BUSCA}"
43 | Click Element ${BOTAO_LUPA}
44 | Input Text ${CAMPO_PESQUISAR} ${BUSCA}
45 | Click Element ${BOTAO_PESQUISAR}
46 | Wait Until Element Is Visible ${LINK_POST}
47 |
48 | Verificar resultado da pesquisa
49 | [Arguments] ${TITULO_POSTAGEM}
50 | Page Should Contain ${TITULO_POSTAGEM}
51 |
52 | Clicar no post encontrado
53 | Click Element ${LINK_POST}
54 |
55 | Verificar tela da postagem
56 | [Arguments] ${TITULO_POSTAGEM}
57 | Wait Until Element Is Visible ${TITULO}
58 | Title Should Be ${TITULO_POSTAGEM}
59 |
60 | Fechar Navegador
61 | Close Browser
--------------------------------------------------------------------------------
/ExemploDataDriven/TestsCasesExemploMaisDeUmTemplate.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Resource Resource.robot
3 | Suite Setup Acessar blog robotizandotestes
4 | Suite Teardown Fechar Navegador
5 | Test Template Validar pesquisa de postagens
6 |
7 | *** Test Case ***
8 | Pesquisar Post Premiere no template 1
9 | [Template] Validar pesquisa de postagens 1
10 | # Busca Título do Post
11 | introdução Season Running - Ep. 08: Executando seus testes no Docker
12 |
13 | Pesquisar Post Premiere no template 2
14 | [Template] Validar pesquisa de postagens 2
15 | # Busca Título do Post
16 | introdução Season Running - Ep. 08: Executando seus testes no Docker
17 |
18 | Pesquisar Post Editores Ep.01 no template 1
19 | [Template] Validar pesquisa de postagens 1
20 | # Busca Título do Post
21 | visual code Season Editores - Ep. 02: Visual Studio Code - Configurando o VS Code para o Robot Framework
22 |
23 | Pesquisar Post Editores Ep.01 no template 2
24 | [Template] Validar pesquisa de postagens 2
25 | # Busca Título do Post
26 | visual code Season Editores - Ep. 02: Visual Studio Code - Configurando o VS Code para o Robot Framework
27 |
28 | Pesquisar Post Tutoriais Ep.01 no template 1
29 | [Template] Validar pesquisa de postagens 1
30 | # Busca Título do Post
31 | windows Season Mobile com Appium - Ep.01: Instalação Windows
32 |
33 | Pesquisar Post Tutoriais Ep.01 no template 2
34 | [Template] Validar pesquisa de postagens 2
35 | # Busca Título do Post
36 | windows Season Mobile com Appium - Ep.01: Instalação Windows
37 |
38 | *** Keyword ***
39 | Validar pesquisa de postagens 1
40 | [Arguments] ${BUSCA} ${TITULO_POSTAGEM}
41 | Pesquisar a postagem pela palavra "${BUSCA}"
42 | Verificar resultado da pesquisa ${TITULO_POSTAGEM}
43 | Clicar no post encontrado
44 | Verificar tela da postagem ${TITULO_POSTAGEM}
45 |
46 | Validar pesquisa de postagens 2
47 | [Arguments] ${BUSCA} ${TITULO_POSTAGEM}
48 | Pesquisar a postagem pela palavra "${BUSCA}"
49 | Verificar resultado da pesquisa ${TITULO_POSTAGEM}
50 | Clicar no post encontrado
51 | Verificar tela da postagem ${TITULO_POSTAGEM}
52 |
--------------------------------------------------------------------------------
/ExemploFakerLibrary/TestCaseExemploFakerLibrary.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Documentation Exemplo de uso da Library Faker
3 | Library FakerLibrary
4 |
5 | *** Test Cases ***
6 | Imprime exemplos de utilidades da library FakerLibrary
7 | Exemplos relacionados a pessoa
8 | Exemplos relacionados a datas
9 | Exemplos diversos
10 |
11 | *** Keywords ***
12 | Exemplos relacionados a pessoa
13 | ${NOMEFAKE} FakerLibrary.Name
14 | ${ENDERECOFAKE} FakerLibrary.Address
15 | ${TELEFONEFAKE} FakerLibrary.Phone Number
16 | ${CIDADEFAKE} FakerLibrary.City
17 | ${CODIGOPOSTALFAKE} FakerLibrary.Postalcode
18 | ${TRABALHOFAKE} FakerLibrary.Job
19 | @{PESSOA} Create List Nome Aleatório: ${NOMEFAKE} Endereço Aleatório: ${ENDERECOFAKE}
20 | ... Telefone Aleatório: ${TELEFONEFAKE} Cidade Aleatória: ${CIDADEFAKE}
21 | ... CódigoPostal Aleatório: ${CODIGOPOSTALFAKE} Trabalho: ${TRABALHOFAKE}
22 | Log Many @{PESSOA}
23 |
24 | Exemplos relacionados a datas
25 | ${DATAFAKE} FakerLibrary.Date
26 | ${MESFAKE} FakerLibrary.Month
27 | ${ANOFAKE} FakerLibrary.Year
28 | ${DIADASEMANAFAKE} FakerLibrary.Day Of Week
29 | ${DIADOMESFAKE} FakerLibrary.Day Of Month
30 | @{DATAS} Create List Data Aleatória: ${DATAFAKE} Mês Aleatório: ${MESFAKE} Ano Aleatório: ${ANOFAKE}
31 | ... Dia da Semana Aleatório: ${DIADASEMANAFAKE} Dia do Mês Aleatório: ${DIADOMESFAKE}
32 | Log Many @{DATAS}
33 |
34 | Exemplos diversos
35 | ${EMAILFAKE} FakerLibrary.Email
36 | ${PASSWORDFAKE} FakerLibrary.Password
37 | ${CORFAKE} FakerLibrary.Color Name
38 | ${CARTAODECREDITOFAKE} FakerLibrary.Credit Card Number
39 | ${PALAVRAFAKE} FakerLibrary.Word
40 | @{OUTROS} Create List E-mail Aleatório: ${EMAILFAKE} Senha Aleatória: ${PASSWORDFAKE}
41 | ... Cor Aleatório: ${CORFAKE} Cartão de Crédito Aleatório: ${CARTAODECREDITOFAKE}
42 | ... Palavra Aleatória: ${PALAVRAFAKE}
43 | Log Many @{OUTROS}
44 |
--------------------------------------------------------------------------------
/ExemploSOAPTesting/MyCustomSudsLibrary/monkeypatches.py:
--------------------------------------------------------------------------------
1 | # Copyright 2012 Kevin Ormbrek
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | import sys
16 | import xml.dom.minidom
17 | from suds.sax.document import Document
18 |
19 |
20 | py_version = sys.version_info[0] + sys.version_info[1] * 0.1
21 | if py_version < 3.3:
22 | class _ElementMonkeyPathes(object):
23 | # from http://ronrothman.com/public/leftbraned/xml-dom-minidom-toprettyxml-and-silly-whitespace/
24 |
25 | def fixed_writexml(self, writer, indent="", addindent="", newl=""):
26 | writer.write(indent + "<" + self.tagName)
27 | attrs = self._get_attributes()
28 | a_names = list(attrs.keys())
29 | a_names.sort()
30 | for a_name in a_names:
31 | writer.write(" %s=\"" % a_name)
32 | xml.dom.minidom._write_data(writer, attrs[a_name].value)
33 | writer.write("\"")
34 | if self.childNodes:
35 | if len(self.childNodes) == 1 \
36 | and self.childNodes[0].nodeType == xml.dom.minidom.Node.TEXT_NODE:
37 | writer.write(">")
38 | self.childNodes[0].writexml(writer, "", "", "")
39 | writer.write("%s>%s" % (self.tagName, newl))
40 | return
41 | writer.write(">%s" % newl)
42 | for node in self.childNodes:
43 | node.writexml(writer, indent + addindent, addindent, newl)
44 | writer.write("%s%s>%s" % (indent, self.tagName, newl))
45 | else:
46 | writer.write("/>%s" % newl)
47 |
48 | xml.dom.minidom.Element.writexml = fixed_writexml
49 |
50 |
51 | class _DocumentMonkeyPatches(object):
52 | # fixes AttributeError in debug log event that fails the keyword
53 |
54 | def str(self):
55 | s = []
56 | s.append(self.DECL)
57 | s.append('\n')
58 | s.append(self.root().str() if self.root() is not None else '')
59 | return ''.join(s)
60 |
61 | Document.str = str
62 |
--------------------------------------------------------------------------------
/SuitePalestraGUTS/SuiteExemploAPI/Resource.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library RequestsLibrary
3 | Library Collections
4 |
5 | *** Variable ***
6 | ${HOST} https://webmaniabr.com/api/1/cep
7 | ${APP_KEY} njMf2EiyQ17g6C3vLUxk1yEsWTforVqf
8 | ${APP_SECRET} EgpTuUcM93IqHY8icgR3cK6Cn4bOlkQwSlfLd6ryMjrhhwMW
9 |
10 | *** Keywords ***
11 | #### DADO
12 | Que esteja conectado no webservice de consultas de CEP
13 | Conecta ao WebService
14 |
15 | #### QUANDO
16 | O usuário consultar o CEP "${CEP_CONSULTADO}"
17 | Realiza requisição do CEP ${CEP_CONSULTADO}
18 |
19 | #### ENTÃO
20 | Deve ser mostrado o endereço "${ENDERECO}"
21 | Confere o status code 200
22 | Confere endereço do CEP ${ENDERECO}
23 |
24 | Deve ser mostrado o bairro "${BAIRRO}"
25 | Confere bairro do CEP ${BAIRRO}
26 |
27 | Deve ser mostrada a cidade "${CIDADE}"
28 | Confere cidade do CEP ${CIDADE}
29 |
30 | Deve ser mostrada a UF "${UF}"
31 | Confere UF do CEP ${UF}
32 |
33 | Deve ser mostrado o CEP "${CEP}"
34 | Confere CEP ${CEP}
35 |
36 | Nenhum dado deve ser mostrado para o CEP "${CEP}"
37 | Confere o status code 200
38 | Confere endereço do CEP ${EMPTY}
39 | Confere bairro do CEP ${EMPTY}
40 | Confere cidade do CEP ${EMPTY}
41 | Confere UF do CEP ${EMPTY}
42 | Confere CEP ${CEP}
43 |
44 | #### PASSOS
45 | Conecta ao WebService
46 | Create Session consultaCEP ${HOST}
47 |
48 | Realiza requisição do CEP
49 | [Arguments] ${CEP_DESEJADO}
50 | ${RESPOSTA}= Get Request consultaCEP /${CEP_DESEJADO}/?app_key=${APP_KEY}&app_secret=${APP_SECRET}
51 | Log Resposta: ${RESPOSTA.text}
52 | Set Test Variable ${RESPOSTA}
53 |
54 | Confere o status code
55 | [Arguments] ${STATUS_ESPERADO}
56 | Log Status Code Retornado: ${RESPOSTA.status_code} -- Status Code Esperado: ${STATUS_ESPERADO}
57 | Should Be Equal As Strings ${RESPOSTA.status_code} ${STATUS_ESPERADO}
58 |
59 | Confere endereço do CEP
60 | [Arguments] ${ENDERECO}
61 | Dictionary Should Contain Item ${RESPOSTA.json()} endereco ${ENDERECO}
62 |
63 | Confere bairro do CEP
64 | [Arguments] ${BAIRRO}
65 | Dictionary Should Contain Item ${RESPOSTA.json()} bairro ${BAIRRO}
66 |
67 | Confere cidade do CEP
68 | [Arguments] ${CIDADE}
69 | Dictionary Should Contain Item ${RESPOSTA.json()} cidade ${CIDADE}
70 |
71 | Confere UF do CEP
72 | [Arguments] ${UF}
73 | Dictionary Should Contain Item ${RESPOSTA.json()} uf ${UF}
74 |
75 | Confere CEP
76 | [Arguments] ${CEP}
77 | Dictionary Should Contain Item ${RESPOSTA.json()} cep ${CEP}
--------------------------------------------------------------------------------
/SuitePalestraGUTS/SuiteExemploWEB/ResourceCadastroQANinja.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library SeleniumLibrary
3 | Library FakerLibrary
4 |
5 | *** Variables ***
6 | ${URL} http://ninjainvoices.herokuapp.com/
7 | ${NAVEGADOR} chrome
8 | ${TITULO_PAGINA} Ninja Invoices
9 | ${BOTAO_CADASTRO} xpath=.//*[@id="register"]
10 | ${TITULO_PAGINA_CADASTRO} css=#register_form > h5
11 | ${TEXTO_ESPERADO_PAGINA_CAD} Seja bem vindo ao Invoices faça seu cadastro aqui
12 | ${CAMPO_NOME} register_name
13 | ${CAMPO_EMAIL} register_email
14 | ${CAMPO_SENHA} register_password
15 | ${BOTAO_CAD_USUARIO} register_form
16 | ${TITULO_PAGINA_BOASVINDAS} xpath=.//*[@id="page_title"]
17 | ${NOME_USUARIO} Usuario Novo Teste
18 | ${EMAIL_INVALIDO} teste_email_invalido
19 | ${ALERTA} xpath=.//div[@class='alert alert-warning']
20 | ${ALERTA_EMAIL_INVALIDO} Please enter valid e-mail address.
21 |
22 | *** Keywords ***
23 | Acessar Página Principal
24 | Open Browser ${URL} ${NAVEGADOR}
25 | Maximize Browser Window
26 | Sleep 1
27 | Title Should Be ${TITULO_PAGINA}
28 |
29 | Clicar em Cadastro
30 | Wait Until Element Is Enabled ${BOTAO_CADASTRO}
31 | Click Element ${BOTAO_CADASTRO}
32 | Wait Until Element Is Visible ${TITULO_PAGINA_CADASTRO}
33 | Element Text Should Be ${TITULO_PAGINA_CADASTRO} ${TEXTO_ESPERADO_PAGINA_CAD}
34 |
35 | Inserir Nome Completo
36 | Wait Until Element Is Enabled ${CAMPO_NOME}
37 | Input Text ${CAMPO_NOME} ${NOME_USUARIO}
38 |
39 | Inserir Email Válido
40 | Wait Until Element Is Enabled ${CAMPO_EMAIL}
41 | ${EMAIL_USUARIO}= FakerLibrary.Email
42 | Input Text ${CAMPO_EMAIL} ${EMAIL_USUARIO}
43 |
44 | Inserir Senha
45 | Wait Until Element Is Enabled ${CAMPO_SENHA}
46 | ${SENHA_USUARIO}= FakerLibrary.Password 8 True
47 | Input Password ${CAMPO_SENHA} ${SENHA_USUARIO}
48 |
49 | Submeter Cadastro
50 | Wait Until Element Is Enabled ${BOTAO_CAD_USUARIO}
51 | Sleep 1
52 | Submit Form ${BOTAO_CAD_USUARIO}
53 |
54 | Conferir Mensagem de Boas Vindas
55 | Wait Until Element Is Visible ${TITULO_PAGINA_BOASVINDAS}
56 | Sleep 2
57 | Page Should Contain Olá, ${NOME_USUARIO}, seja bem vindo ao Invoices.
58 |
59 | Inserir Email Inválido
60 | Wait Until Element Is Enabled ${CAMPO_EMAIL}
61 | Input Text ${CAMPO_EMAIL} ${EMAIL_INVALIDO}
62 |
63 | Conferir Mensagem de Alerta de Email Inválido
64 | Wait Until Element Is Enabled ${ALERTA}
65 | Sleep 2
66 | Element Text Should Be ${ALERTA} ${ALERTA_EMAIL_INVALIDO}
--------------------------------------------------------------------------------
/ExemploLibraryXML/ResourceXML.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library OperatingSystem
3 | Library String
4 | Library XML
5 |
6 | *** Keywords ***
7 | Manipular e conferir XML
8 | ############ OPÇÃO 01 - Manipular como STRING ############
9 | ### Pegue um XML no diretório, armazene em uma variável e manipule como STRING
10 | ${XML_CONTENT} Get File xmlBaseExemplo.xml
11 | ${XML_CONTENT} Replace String ${XML_CONTENT} ID_ANTES ID_DEPOIS
12 | Log ${XML_CONTENT}
13 |
14 | ############ OPÇÃO 02 - Manipular como XML ############
15 | ### Pegando Elementos e Atributos com a library XML
16 | ${ELEMENTO} Get Element Text ${XML_CONTENT} xpath=.//idConsultante
17 | Log ${ELEMENTO}
18 | ${ATRIBUTO} Get Element Attribute ${XML_CONTENT} nome xpath=.//outroParametro[1]
19 | Log ${ATRIBUTO}
20 |
21 | ### Manipulando Elementos com a library XML
22 | ${XML_CONTENT} Remove Element ${XML_CONTENT} xpath=.//senhaConsultante
23 | Log Element ${XML_CONTENT}
24 | ${XML_CONTENT} Add Element ${XML_CONTENT} 9999999 xpath=.//consultarAvisosPendentes index=2
25 | Log Element ${XML_CONTENT}
26 | ${XML_CONTENT} Set Element Text ${XML_CONTENT} 02072019 xpath=.//dataReferencia
27 | Log Element ${XML_CONTENT}
28 | ${XML_CONTENT} Add Element ${XML_CONTENT} true xpath=.//consultarAvisosPendentes
29 | ${XML_CONTENT} Set Element Attribute ${XML_CONTENT} nome mayara xpath=.//outroParametro[3]
30 | ${XML_CONTENT} Set Element Attribute ${XML_CONTENT} valor QA xpath=.//outroParametro[3]
31 | Log Element ${XML_CONTENT}
32 |
33 | ### Após manipular, salve o XML e use como preferir
34 | Save Xml ${XML_CONTENT} meuXMLmanipulado.xml
35 | ${XML_FINAL} Get File meuXMLmanipulado.xml
36 | Log ${XML_FINAL}
37 |
38 | ### Conferências com a library XML
39 | Element Text Should Be ${XML_FINAL} ID_DEPOIS xpath=.//idConsultante
40 | Element Attribute Should Be ${XML_FINAL} nome atendimentoPlantao xpath=.//outroParametro[1]
41 | Element Attribute Should Be ${XML_FINAL} valor false xpath=.//outroParametro[1]
42 | Element Attribute Should Be ${XML_FINAL} nome urgente xpath=.//outroParametro[2]
43 | Element Attribute Should Be ${XML_FINAL} valor true xpath=.//outroParametro[2]
44 | Element Attribute Should Be ${XML_FINAL} nome mayara xpath=.//outroParametro[3]
45 | Element Attribute Should Be ${XML_FINAL} valor QA xpath=.//outroParametro[3]
46 |
--------------------------------------------------------------------------------
/Demos/DemoAPI/Resource.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library RequestsLibrary
3 | Library Collections
4 |
5 | *** Variable ***
6 | ${HOST} https://webmaniabr.com/api/1/cep
7 | ${APP_KEY} njMf2EiyQ17g6C3vLUxk1yEsWTforVqf
8 | ${APP_SECRET} EgpTuUcM93IqHY8icgR3cK6Cn4bOlkQwSlfLd6ryMjrhhwMW
9 |
10 | *** Keywords ***
11 | #### DADO
12 | Que esteja conectado no webservice de consultas de CEP
13 | Conecta ao WebService
14 |
15 | #### QUANDO
16 | O usuário consultar o CEP "${CEP_CONSULTADO}"
17 | Realiza requisição do CEP ${CEP_CONSULTADO}
18 |
19 | #### ENTÃO
20 | Deve ser mostrado o endereço "${ENDERECO}"
21 | Confere o status code 200
22 | Confere endereço do CEP ${ENDERECO}
23 |
24 | Deve ser mostrado o bairro "${BAIRRO}"
25 | Confere bairro do CEP ${BAIRRO}
26 |
27 | Deve ser mostrada a cidade "${CIDADE}"
28 | Confere cidade do CEP ${CIDADE}
29 |
30 | Deve ser mostrada a UF "${UF}"
31 | Confere UF do CEP ${UF}
32 |
33 | Deve ser mostrado o CEP "${CEP}"
34 | Confere CEP ${CEP}
35 |
36 | ##Cenário 02 Depreciado em 12/04/2019 devido atualização na API
37 | # Nenhum dado deve ser mostrado para o CEP "${CEP}"
38 | # Confere o status code 200
39 | # Confere endereço do CEP ${EMPTY}
40 | # Confere bairro do CEP ${EMPTY}
41 | # Confere cidade do CEP ${EMPTY}
42 | # Confere UF do CEP ${EMPTY}
43 | # Confere CEP ${CEP}
44 |
45 | A mensagem de erro "${MSG_ERRO}" deve ser retornada
46 | Confere o status code 200
47 | Confere mensagem de erro ${MSG_ERRO}
48 |
49 | #### PASSOS
50 | Conecta ao WebService
51 | Create Session consultaCEP ${HOST}
52 |
53 | Realiza requisição do CEP
54 | [Arguments] ${CEP_DESEJADO}
55 | ${RESPOSTA}= Get Request consultaCEP /${CEP_DESEJADO}/?app_key=${APP_KEY}&app_secret=${APP_SECRET}
56 | Log Resposta: ${RESPOSTA.text}
57 | Set Test Variable ${RESPOSTA}
58 |
59 | Confere o status code
60 | [Arguments] ${STATUS_ESPERADO}
61 | Should Be Equal As Strings ${RESPOSTA.status_code} ${STATUS_ESPERADO}
62 | Log Status Code Retornado: ${RESPOSTA.status_code} -- Status Code Esperado: ${STATUS_ESPERADO}
63 |
64 | Confere endereço do CEP
65 | [Arguments] ${ENDERECO}
66 | Dictionary Should Contain Item ${RESPOSTA.json()} endereco ${ENDERECO}
67 |
68 | Confere bairro do CEP
69 | [Arguments] ${BAIRRO}
70 | Dictionary Should Contain Item ${RESPOSTA.json()} bairro ${BAIRRO}
71 |
72 | Confere cidade do CEP
73 | [Arguments] ${CIDADE}
74 | Dictionary Should Contain Item ${RESPOSTA.json()} cidade ${CIDADE}
75 |
76 | Confere UF do CEP
77 | [Arguments] ${UF}
78 | Dictionary Should Contain Item ${RESPOSTA.json()} uf ${UF}
79 |
80 | Confere CEP
81 | [Arguments] ${CEP}
82 | Dictionary Should Contain Item ${RESPOSTA.json()} cep ${CEP}
83 |
84 | Confere mensagem de erro
85 | [Arguments] ${MSG_ERRO}
86 | Dictionary Should Contain Item ${RESPOSTA.json()} error ${MSG_ERRO}
87 |
--------------------------------------------------------------------------------
/SuiteCadastroQANinja/ResourceCadastroQANinja.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library Selenium2Library
3 | Library FakerLibrary
4 |
5 | *** Variables ***
6 | ${URL} http://ninjainvoices.herokuapp.com/
7 | ${NAVEGADOR} chrome
8 | ${TITULO_PAGINA} Ninja Invoices
9 | ${BOTAO_CADASTRO} xpath=.//*[@id="register"]
10 | ${TITULO_PAGINA_CADASTRO} css=#register_form > h5
11 | ${TEXTO_ESPERADO_PAGINA_CAD} Seja bem vindo ao Invoices faça seu cadastro aqui
12 | ${CAMPO_NOME} register_name
13 | ${CAMPO_EMAIL} register_email
14 | ${CAMPO_SENHA} register_password
15 | ${BOTAO_CAD_USUARIO} register_form
16 | ${TITULO_PAGINA_BOASVINDAS} xpath=.//*[@id="page_title"]
17 | ${NOME_USUARIO} Usuario Novo Teste
18 | ${EMAIL_INVALIDO} teste_email_invalido
19 | ${ALERTA} xpath=.//div[@class='alert alert-warning']
20 | ${ALERTA_EMAIL_INVALIDO} Please enter valid e-mail address.
21 |
22 | *** Keywords ***
23 | Acessar Página Principal
24 | Open Browser ${URL} ${NAVEGADOR}
25 | Title Should Be ${TITULO_PAGINA}
26 |
27 | Clicar em Cadastro
28 | Wait Until Element Is Enabled ${BOTAO_CADASTRO}
29 | Click Element ${BOTAO_CADASTRO}
30 | Wait Until Element Is Visible ${TITULO_PAGINA_CADASTRO}
31 | ${TEXTO_ATUAL_PAGINA_CAD}= Get Text ${TITULO_PAGINA_CADASTRO}
32 | Element Text Should Be ${TITULO_PAGINA_CADASTRO} ${TEXTO_ESPERADO_PAGINA_CAD} O Título atual [${TEXTO_ATUAL_PAGINA_CAD}] está errado. Esperado: [${TEXTO_ESPERADO_PAGINA_CAD}]
33 |
34 | Inserir Nome Completo
35 | Wait Until Element Is Enabled ${CAMPO_NOME}
36 | Input Text ${CAMPO_NOME} ${NOME_USUARIO}
37 |
38 | Inserir Email Válido
39 | Wait Until Element Is Enabled ${CAMPO_EMAIL}
40 | ${EMAIL_USUARIO}= FakerLibrary.Email
41 | Input Text ${CAMPO_EMAIL} ${EMAIL_USUARIO}
42 |
43 | Inserir Senha
44 | Wait Until Element Is Enabled ${CAMPO_SENHA}
45 | ${SENHA_USUARIO}= FakerLibrary.Password 8 True
46 | Input Password ${CAMPO_SENHA} ${SENHA_USUARIO}
47 |
48 | Submeter Cadastro
49 | Wait Until Element Is Enabled ${BOTAO_CAD_USUARIO}
50 | Submit Form ${BOTAO_CAD_USUARIO}
51 |
52 | Conferir Mensagem de Boas Vindas
53 | Wait Until Element Is Visible ${TITULO_PAGINA_BOASVINDAS}
54 | Page Should Contain Olá, ${NOME_USUARIO}, seja bem vindo ao Invoices.
55 |
56 | Inserir Email Inválido
57 | Wait Until Element Is Enabled ${CAMPO_EMAIL}
58 | Input Text ${CAMPO_EMAIL} ${EMAIL_INVALIDO}
59 |
60 | Conferir Mensagem de Alerta de Email Inválido
61 | Wait Until Element Is Enabled ${ALERTA}
62 | ${ALERTA_ATUAL}= Get Text ${ALERTA}
63 | Element Text Should Be ${ALERTA} ${ALERTA_EMAIL_INVALIDO} O Alerta atual [${ALERTA_ATUAL}] está errado. Esperado: [${ALERTA_EMAIL_INVALIDO}]
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/ExemploSOAPTesting/MyCustomSudsLibrary/factory.py:
--------------------------------------------------------------------------------
1 | # Copyright 2012 Kevin Ormbrek
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | from suds.sudsobject import Object as SudsObject
16 |
17 |
18 | class _FactoryKeywords(object):
19 |
20 | def set_wsdl_object_attribute(self, object, name, value):
21 | """Sets the attribute of a WSDL object.
22 |
23 | Example:
24 | | ${order search request}= | Create Wsdl Object | OrderSearchRequest | |
25 | | Set Wsdl Object Attribute | ${order search request} | id | 4065 |
26 | """
27 | self._assert_is_suds_object(object)
28 | getattr(object, name)
29 | setattr(object, name, value)
30 |
31 | def get_wsdl_object_attribute(self, object, name):
32 | """Gets the attribute of a WSDL object.
33 |
34 | Extendend variable syntax may be used to access attributes; however,
35 | some WSDL objects may have attribute names that are illegal in Python,
36 | necessitating this keyword.
37 |
38 | Example:
39 | | ${sale record}= | Call Soap Method | getLastSale | |
40 | | ${price}= | Get Wsdl Object Attribute | ${sale record} | Price |
41 | """
42 | self._assert_is_suds_object(object)
43 | return getattr(object, name)
44 |
45 | def create_wsdl_object(self, type, *name_value_pairs):
46 | """Creates a WSDL object of the specified `type`.
47 |
48 | Requested `type` must be defined in the WSDL, in an import specified
49 | by the WSDL, or with `Add Doctor Import`. `type` is case sensitive.
50 |
51 | Example:
52 | | ${contact}= | Create Wsdl Object | Contact | |
53 | | Set Wsdl Object Attribute | ${contact} | Name | Kelly Newman |
54 | Attribute values can be set by passing the attribute name and value in
55 | pairs. This is equivalent to the two lines above:
56 | | ${contact}= | Create Wsdl Object | Contact | Name | Kelly Newman |
57 | """
58 | if len(name_value_pairs) % 2 != 0:
59 | raise ValueError("Creating a WSDL object failed. There should be "
60 | "an even number of name-value pairs.")
61 | obj = self._client().factory.create(type)
62 | for i in range(0, len(name_value_pairs), 2):
63 | self.set_wsdl_object_attribute(obj, name_value_pairs[i], name_value_pairs[i + 1])
64 | return obj
65 |
66 | # private
67 |
68 | def _assert_is_suds_object(self, object):
69 | if not isinstance(object, SudsObject):
70 | raise ValueError("Object must be a WSDL object (suds.sudsobject.Object).")
71 |
--------------------------------------------------------------------------------
/ExemploAPI_ServeRest/Exemplo_API_ServeRest.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Documentation Testes utilizando as novas keywords da RequestsLibrary na versão 8
3 | Library RequestsLibrary
4 | Library Collections
5 | Library FakerLibrary locale=pt_br
6 |
7 |
8 | *** Variables ***
9 | ${ALIAS} API_serverest
10 |
11 |
12 | *** Test Cases ***
13 | Testar a API pública de estudos serverest
14 | Iniciar sessão na API serverest
15 | Cadastrar usuário de teste
16 | Obter Token
17 | Cadastrar um produto
18 | Listar o produto cadastrado
19 |
20 |
21 | *** Keywords ***
22 | Cria dados aleatórios do usuário
23 | ${RANDOM_NOME_FIRST} FakerLibrary.First Name
24 | ${RANDOM_NOME_LAST} FakerLibrary.Last Name
25 | ${RANDOM_EMAIL} FakerLibrary.Email
26 | ${RANDOM_PWD} FakerLibrary.Password
27 | ${USUARIO} Create Dictionary nome=${RANDOM_NOME_FIRST} ${RANDOM_NOME_LAST} email=${RANDOM_EMAIL} senha=${RANDOM_PWD}
28 | Set Suite Variable ${USUARIO}
29 |
30 | Iniciar sessão na API serverest
31 | ${HEADERS} Create Dictionary Content-Type=application/json
32 | Create Session alias=${ALIAS} url=https://serverest.dev headers=${HEADERS} disable_warnings=1
33 |
34 | Cadastrar usuário de teste
35 | Cria dados aleatórios do usuário
36 | ${BODY} Create Dictionary nome=${USUARIO.nome} email=${USUARIO.email} password=${USUARIO.senha} administrador=true
37 | ${RESPONSE} POST On Session alias=${ALIAS} url=usuarios json=${BODY}
38 | Log Resposta Retornada: ${\n}${RESPONSE.text}
39 |
40 | Obter Token
41 | ${BODY} Create Dictionary email=${USUARIO.email} password=${USUARIO.senha}
42 | ${RESPONSE} POST On Session alias=${ALIAS} url=login json=${BODY}
43 | Log Resposta Retornada: ${\n}${RESPONSE.text}
44 | Dictionary Should Contain Item ${RESPONSE.json()} message Login realizado com sucesso
45 | ${TOKEN} Get From Dictionary ${RESPONSE.json()} authorization
46 | Set Suite Variable ${TOKEN}
47 |
48 | Cadastrar um produto
49 | ${RANDOM_PROD} FakerLibrary.Word
50 | Set Suite Variable ${RANDOM_PROD}
51 | ${BODY} Create Dictionary nome=${RANDOM_PROD} preco=155 descricao=meu produto de teste quantidade=10
52 | ${HEADERS} Create Dictionary Authorization=${TOKEN}
53 | ${RESPONSE} POST On Session alias=${ALIAS} url=produtos json=${BODY} headers=${HEADERS}
54 | Log Resposta Retornada: ${\n}${RESPONSE.text}
55 | Dictionary Should Contain Item ${RESPONSE.json()} message Cadastro realizado com sucesso
56 | ${ID_PRODUTO_CADASTRADO} Get From Dictionary ${RESPONSE.json()} _id
57 | Set Suite Variable ${ID_PRODUTO_CADASTRADO}
58 |
59 | Listar o produto cadastrado
60 | ${HEADERS} Create Dictionary Authorization=${TOKEN}
61 | ${RESPONSE} GET On Session alias=${ALIAS} url=produtos/${ID_PRODUTO_CADASTRADO} headers=${HEADERS}
62 | Log Resposta Retornada: ${\n}${RESPONSE.text}
63 | Dictionary Should Contain Item ${RESPONSE.json()} nome ${RANDOM_PROD}
64 | Dictionary Should Contain Item ${RESPONSE.json()} preco 155
65 | Dictionary Should Contain Item ${RESPONSE.json()} descricao meu produto de teste
66 | Dictionary Should Contain Item ${RESPONSE.json()} quantidade 10
67 | Dictionary Should Contain Key ${RESPONSE.json()} _id
68 |
--------------------------------------------------------------------------------
/RabbitMQ/ResourceRabbitMQ.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library ./RabbitMQCustom.py
3 | Library RequestsLibrary
4 | Library Collections
5 |
6 | *** Keywords ***
7 | Conectar no RabbitMQ
8 | [Documentation] Efetua a conexão com o RabbitMQ.
9 | [Arguments] ${RABBIT_HOST} ${RABBIT_PORT} ${RABBIT_USER} ${RABBIT_PASSWORD} ${RABBIT_ALIAS}=rmq_http
10 | Connect To RabbitMQ host=${RABBIT_HOST}
11 | ... port=${RABBIT_PORT}
12 | ... username=${RABBIT_USER}
13 | ... password=${RABBIT_PASSWORD}
14 | ... alias=${RABBIT_ALIAS}
15 |
16 | Criar fila com prioridade no RabbitMQ
17 | [Documentation] Cria uma fila com prioridade. Default prioridade=5.
18 | [Arguments] ${FILA} ${PRIORIDADE}=${5}
19 | ${ARGUMENTS} Create Dictionary x-max-priority=${PRIORIDADE}
20 | Create Queues By Name ${FILA} arguments=${ARGUMENTS}
21 |
22 | Criar filas com prioridade no RabbitMQ
23 | [Documentation] Cria as filas listadas na lista enviada, com prioridade. Default prioridade=5.
24 | [Arguments] @{FILAS_CRIAR} ${PRIORIDADE}=${5}
25 | FOR ${FILA} IN @{FILAS_CRIAR}
26 | Criar fila com prioridade no RabbitMQ ${FILA} ${PRIORIDADE}
27 | END
28 |
29 | Limpar todas as filas do RabbitMQ
30 | [Documentation] Limpa (purge) as filas listadas na lista enviada.
31 | [Arguments] @{FILAS_LIMPAR}
32 | FOR ${FILA} IN @{FILAS_LIMPAR}
33 | Purge Messages By Queue ${FILA}
34 | END
35 |
36 | Fechar conexão com o RabbitMQ
37 | [Documentation] Encerra a conexão com o RabbitMQ.
38 | Disconnect From RabbitMQ
39 |
40 | ###### Requisições
41 | Realizar requisição POST no RabbitMQ
42 | [Documentation] Publica uma mensagem em uma determinada fila sem envio de headers.
43 | [Arguments] ${MENSAGEM} ${FILA}
44 | &{PROPERTIES} Create Dictionary delivery_mode=${1}
45 | ${PUBLISH} Publish Message By Name queue=${FILA} msg=${MENSAGEM} properties=${PROPERTIES}
46 | Verificar sucesso no publish ${PUBLISH}
47 |
48 | Realizar requisição POST com HEADERS no RabbitMQ
49 | [Documentation] Publica uma mensagem em uma determinada fila com envio de headers.
50 | [Arguments] ${MENSAGEM} ${FILA} ${HEADERS}
51 | &{PROPERTIES} Create Dictionary delivery_mode=${1} headers=${HEADERS}
52 | ${PUBLISH} Publish Message By Name queue=${FILA} msg=${MENSAGEM} properties=${PROPERTIES}
53 | Verificar sucesso no publish ${PUBLISH}
54 |
55 | Verificar sucesso no publish
56 | [Documentation] Verifica se houve sucesso em um publish realizado.
57 | [Arguments] ${PUBLISH}
58 | Log Dictionary ${PUBLISH}
59 | ${ROUTED} Get From Dictionary ${PUBLISH} routed
60 | Should be True ${ROUTED} msg=Não foi possível publicar no RabbitMQ. Verifique!
61 |
62 | Realizar requisição GET de uma mensagem no RabbitMQ
63 | [Documentation] Pega a primeira mensagem da fila especificada. Faz tentativas de obtê-la até um limite de tempo. Default limte_wait=75.
64 | [Arguments] ${FILA} ${LIMITE_WAIT}=75
65 | FOR ${SEGUNDO} IN RANGE 0 ${LIMITE_WAIT}
66 | ${RESPOSTA} Run Keyword And Ignore Error Get Messages by Queue ${FILA} 1
67 | ${TAMANHO} Get Length ${RESPOSTA[1]}
68 | Exit For Loop If ${TAMANHO} > 0 and '${RESPOSTA[0]}'=='PASS'
69 | Run Keyword If '${RESPOSTA[1]}' == 'CannotSendRequest: Request-sent' Sleep 3s ELSE Sleep 0.2s
70 | END
71 | Log Mensagem retornada:${\n}${RESPOSTA[1]}
72 | Validar se retornou mensagens ${RESPOSTA[1]} ${FILA}
73 | ${RESPOSTA} To Json ${RESPOSTA[1]["payload"]}
74 | [Return] ${RESPOSTA}
75 |
76 | Realizar requisição GET de várias mensagens no RabbitMQ
77 | [Documentation] Pega as primeiras N mensagens da fila especificada.
78 | [Arguments] ${FILA} ${COUNT}
79 | ${RESPOSTA} Get Messages by Queue ${FILA} ${COUNT}
80 | Log Mensagens retornadas:${\n}${RESPOSTA}
81 | Validar se retornou mensagens ${RESPOSTA} ${FILA}
82 | ${RESPOSTA} To Json ${RESPOSTA[0]["payload"]}
83 | [Return] ${RESPOSTA}
84 |
85 | Validar se retornou mensagens
86 | [Arguments] ${RESPOSTA} ${FILA}
87 | ${TAMANHO} Get Length ${RESPOSTA[1]}
88 | Run Keyword If ${TAMANHO} == 0 Fail Não há mensagens na fila [${FILA}]. Verifique!
89 |
--------------------------------------------------------------------------------
/ExemploSOAPTesting/MyCustomSudsLibrary/soaplogging.py:
--------------------------------------------------------------------------------
1 | # Copyright 2012 Kevin Ormbrek
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | import xml.dom.minidom
16 | from xml.parsers.expat import ExpatError
17 | from suds.plugin import MessagePlugin
18 | from robot.api import logger
19 | from .utils import *
20 |
21 |
22 | class _SoapLogger(MessagePlugin):
23 |
24 | def __init__(self):
25 | self._sent = None
26 | self._received = None
27 | self.log = True
28 | self.prettyxml = True
29 | self._indent = 2
30 |
31 | def sending(self, context):
32 | self._sent = context.envelope
33 | self._received = None
34 | if self.log:
35 | logger.info('Sending:\n%s' % self.last_sent(self.prettyxml))
36 |
37 | def last_sent(self, prettyxml=False):
38 | # possible that text inserted into the post body, making it invalid XML
39 | try:
40 | return self._prettyxml(self._sent) if prettyxml else self._sent
41 | except ExpatError:
42 | return self._sent
43 |
44 | def received(self, context):
45 | self._received = context.reply
46 | if self.log:
47 | logger.info('Received:\n%s' % self.last_received(self.prettyxml))
48 |
49 | def last_received(self, prettyxml=False):
50 | return self._prettyxml(self._received) if prettyxml else self._received
51 |
52 | def set_indent(self, indent):
53 | try:
54 | self._indent = int(indent)
55 | except ValueError:
56 | raise ValueError("Cannot convert indent value '%s' to an integer"
57 | % indent)
58 |
59 | def _prettyxml(self, xml_string):
60 | dom = xml.dom.minidom.parseString(xml_string)
61 | return dom.toprettyxml(indent=(self._indent * " "))
62 |
63 |
64 | class _SoapLoggingKeywords(object):
65 |
66 | def set_soap_logging(self, log, prettyxml=None, indent=None):
67 | """Sets whether to log the request and response for the current client.
68 |
69 | By default, the message sent and received is logged at level INFO,
70 | pretty-formatted with an indent of 2 spaces per level. Setting `log`
71 | to false will disable logging, reducing the size of the log. Boolean
72 | option `prettyxml` controls whether the XML is pretty-formatted.
73 | `indent` should be the number of spaces to indent per level. Leaving
74 | `prettyxml` or `indent` at the default value of None will preserve the
75 | previous settings. Returns the current value of log.
76 |
77 | Examples:
78 | | ${old log value} | Set Soap Logging | False | |
79 | | Call Soap Method | lengthyResponse | | |
80 | | Set Soap Logging | True | True | 4 |
81 | """
82 | new_value = to_bool(log)
83 | soap_logger = self._get_soap_logger()
84 | if soap_logger:
85 | old_value = soap_logger.log
86 | else:
87 | soap_logger = self._add_soap_logger()
88 | old_value = False
89 | soap_logger.log = new_value
90 | if not prettyxml is None:
91 | soap_logger.prettyxml = to_bool(prettyxml)
92 | if not indent is None:
93 | soap_logger.set_indent(indent)
94 | return old_value
95 |
96 | def get_last_sent(self):
97 | """Gets the message text last sent.
98 |
99 | Unless a plugin is used to modify the message, it will always be a XML
100 | document."""
101 | soap_logger = self._get_soap_logger(True)
102 | return soap_logger.last_sent(False)
103 |
104 | def get_last_received(self):
105 | """Gets the XML last received."""
106 | soap_logger = self._get_soap_logger(True)
107 | return soap_logger.last_received(False)
108 |
109 | # private
110 |
111 | def _get_soap_logger(self, required=False):
112 | plugins = self._client().options.plugins
113 | matches = [x for x in plugins if isinstance(x, _SoapLogger)]
114 | if matches:
115 | return matches[0]
116 | else:
117 | if required:
118 | raise RuntimeError("The SudsLibrary SOAP logging message plugin has been removed.")
119 | return None
120 |
121 | def _add_soap_logger(self):
122 | client = self._client()
123 | plugins = client.options.plugins
124 | soap_logger = _SoapLogger()
125 | plugins.append(soap_logger)
126 | client.set_options(plugins=plugins)
127 | return soap_logger
128 |
--------------------------------------------------------------------------------
/ExemploSOAPTesting/MyCustomSudsLibrary/proxy.py:
--------------------------------------------------------------------------------
1 | # Copyright 2013 Kevin Ormbrek
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | from suds import WebFault
16 | from suds import byte_str
17 | from suds.sax.text import Raw
18 | from .utils import *
19 | import socket
20 |
21 |
22 | class RawSoapMessage(object):
23 |
24 | def __init__(self, string):
25 | if isinstance(string, bytes):
26 | self.message = string.decode()
27 | else:
28 | self.message = str(string)
29 |
30 | def __str__(self):
31 | return self.message
32 |
33 | def __unicode__(self):
34 | return self.message
35 |
36 |
37 | class _ProxyKeywords(object):
38 |
39 | def call_soap_method(self, name, *args):
40 | """Calls the SOAP method with the given `name` and `args`.
41 |
42 | Returns a Python object graph or SOAP envelope as a XML string
43 | depending on the client options.
44 | """
45 |
46 | return self._call(None, None, False, name, *args)
47 |
48 | def specific_soap_call(self, service, port, name, *args):
49 | """Calls the SOAP method overriding client settings.
50 |
51 | If there is only one service specified then `service` is ignored.
52 | `service` and `port` can be either by name or index. If only `port` or
53 | `service` need to be specified, leave the other one ${None} or
54 | ${EMPTY}. The index is the order of appearence in the WSDL starting
55 | with 0.
56 |
57 | Returns a Python object graph or SOAP envelope as a XML string
58 | depending on the client options.
59 | """
60 |
61 | return self._call(service, port, False, name, *args)
62 |
63 | def call_soap_method_expecting_fault(self, name, *args):
64 | """Calls the SOAP method expecting the server to raise a fault.
65 |
66 | Fails if the server does not raise a fault. Returns a Python object
67 | graph or SOAP envelope as a XML string depending on the client
68 | options.
69 |
70 | A fault has the following attributes:\n
71 | | faultcode | required |
72 | | faultstring | required |
73 | | faultactor | optional |
74 | | detail | optional |
75 | """
76 | return self._call(None, None, True, name, *args)
77 |
78 | def create_raw_soap_message(self, message):
79 | """Returns an object that can used in lieu of SOAP method arguments.
80 |
81 | `message` should be an entire SOAP message as a string. The object
82 | returned can be used in lieu of *args for `Call Soap Method`, `Call
83 | Soap Method Expecting Fault`, and `Specific Soap Call`.
84 |
85 | Example:\n
86 | | ${message}= | Create Raw Soap Message | |
87 | | Call Soap Method | addContact | ${message} |
88 | """
89 | return RawSoapMessage(message)
90 |
91 | # private
92 |
93 | def _call(self, service, port, expect_fault, name, *args):
94 | client = self._client()
95 | self._backup_options()
96 | if service or (service == 0):
97 | client.set_options(service=parse_index(service))
98 | if port or (port == 0):
99 | client.set_options(port=parse_index(port))
100 | method = getattr(client.service, name)
101 | received = None
102 | try:
103 | if len(args) == 1 and isinstance(args[0], RawSoapMessage):
104 | message = byte_str(args[0].message)
105 | received = method(__inject={'msg': message})
106 | else:
107 | received = method(*args)
108 | if expect_fault:
109 | raise AssertionError('The server did not raise a fault.')
110 | except WebFault as e:
111 | if not expect_fault:
112 | raise e
113 | received = e.fault
114 | finally:
115 | self._restore_options()
116 | return_xml = self._get_external_option("return_xml", False)
117 | if return_xml:
118 | received = self.get_last_received()
119 | return received
120 |
121 | # private
122 |
123 | def _backup_options(self):
124 | options = self._client().options
125 | self._old_options = dict([[n, getattr(options, n)] for n in ('service', 'port')])
126 | if self._global_timeout:
127 | self._old_timeout = socket.getdefaulttimeout()
128 |
129 | def _restore_options(self):
130 | self._client().set_options(**self._old_options)
131 | # restore the default socket timeout because suds does not
132 | if self._global_timeout:
133 | socket.setdefaulttimeout(self._old_timeout)
134 |
--------------------------------------------------------------------------------
/ExemploSOAPTesting/MyCustomSudsLibrary/clientmanagement.py:
--------------------------------------------------------------------------------
1 | # Copyright 2012 Kevin Ormbrek
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | import os
16 | import urllib.request, urllib.parse, urllib.error
17 | from suds.xsd.doctor import ImportDoctor
18 | from suds.transport.http import HttpAuthenticated
19 | from urllib.parse import urlparse
20 | from suds.client import Client
21 | from .utils import *
22 |
23 |
24 | class _ClientManagementKeywords(object):
25 |
26 | def create_soap_client(self, url_or_path, alias=None, autoblend=False, timeout='90 seconds', username=None,
27 | password=None, auth_type='STANDARD'):
28 | """Loads a WSDL from the given URL/path and creates a Suds SOAP client.
29 |
30 | Returns the index of this client instance which can be used later to
31 | switch back to it. See `Switch Soap Client` for example.
32 |
33 | Optional alias is an alias for the client instance and it can be used
34 | for switching between clients (just as index can be used). See `Switch
35 | Soap Client` for more details.
36 |
37 | `username` and `password` are needed if the WSDL is on a server
38 | requiring basic authentication. `auth_type` selects the authentication
39 | scheme to use. See `Set Http Authentication` for more information.
40 |
41 | Autoblend ensures that the schema(s) defined within the WSDL import
42 | each other.
43 |
44 | `timeout` sets the timeout for SOAP requests and must be given in
45 | Robot Framework's time format (e.g. '1 minute', '2 min 3 s', '4.5').
46 |
47 | Examples:
48 | | Create Soap Client | http://localhost:8080/ws/Billing.asmx?WSDL |
49 | | Create Soap Client | ${CURDIR}/../wsdls/tracking.wsdl |
50 | """
51 | url = self._get_url(url_or_path)
52 | autoblend = to_bool(autoblend)
53 | kwargs = {'autoblend': autoblend}
54 | if username:
55 | password = password if password is not None else ""
56 | transport = self._get_transport(auth_type, username, password)
57 | kwargs['transport'] = transport
58 | imports = self._imports
59 | if imports:
60 | self._log_imports()
61 | kwargs['doctor'] = ImportDoctor(*imports)
62 | client = Client(url, **kwargs)
63 | index = self._add_client(client, alias)
64 | self._set_soap_timeout(timeout)
65 | return index
66 |
67 | def switch_soap_client(self, index_or_alias):
68 | """Switches between clients using index or alias.
69 |
70 | Index is returned from `Create Soap Client` and alias can be given to
71 | it.
72 |
73 | Example:
74 | | Create Soap Client | http://localhost:8080/Billing?wsdl | Billing |
75 | | Create Soap Client | http://localhost:8080/Marketing?wsdl | Marketing |
76 | | Call Soap Method | sendSpam | |
77 | | Switch Soap Client | Billing | # alias |
78 | | Call Soap Method | sendInvoices | |
79 | | Switch Soap Client | 2 | # index |
80 |
81 | Above example expects that there was no other clients created when
82 | creating the first one because it used index '1' when switching to it
83 | later. If you aren't sure about that you can store the index into
84 | a variable as below.
85 |
86 | | ${id} = | Create Soap Client | ... |
87 | | # Do something ... | | |
88 | | Switch Soap Client | ${id} | |
89 | """
90 | self._cache.switch(index_or_alias)
91 |
92 | # PyAPI
93 |
94 | def _client(self):
95 | """Returns the current suds.client.Client instance."""
96 | return self._cache.current
97 |
98 | def _add_client(self, client, alias=None):
99 | """Puts a client into the cache and returns the index.
100 |
101 | The added client becomes the current one."""
102 | client.set_options(faults=True)
103 | self._logger.info('Using WSDL at %s%s' % (client.wsdl.url, client))
104 | self._imports = []
105 | index = self._cache.register(client, alias)
106 | self.set_soap_logging(True)
107 | return index
108 |
109 | # private
110 |
111 | def _log_imports(self):
112 | if self._imports:
113 | msg = "Using Imports for ImportDoctor:"
114 | for imp in self._imports:
115 | msg += "\n Namespace: '%s' Location: '%s'" % (imp.ns, imp.location)
116 | for ns in imp.filter.tns:
117 | msg += "\n Filtering for namespace '%s'" % ns
118 | self._logger.info(msg)
119 |
120 | def _get_url(self, url_or_path):
121 | if not len(urlparse(url_or_path).scheme) > 1:
122 | if not os.path.isfile(url_or_path):
123 | raise IOError("File '%s' not found." % url_or_path)
124 | url_or_path = 'file:' + urllib.request.pathname2url(url_or_path)
125 | return url_or_path
126 |
--------------------------------------------------------------------------------
/ExemploSOAPTesting/MyCustomSudsLibrary/wsse.py:
--------------------------------------------------------------------------------
1 | # Copyright 2013 Kevin Ormbrek
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | from .utils import *
16 | from suds.wsse import Security
17 | from suds.wsse import Token
18 | from suds.wsse import Timestamp
19 | from suds.wsse import UsernameToken
20 | from suds.sax.element import Element
21 | from random import random
22 | from hashlib import sha1
23 | import base64
24 | import re
25 | from datetime import timedelta, datetime
26 | import robot
27 |
28 |
29 | TEXT_TYPE = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText'
30 | DIGEST_TYPE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest"
31 | BASE64_ENC_TYPE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
32 | WSSENS = \
33 | ('wsse',
34 | 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd')
35 | WSUNS = \
36 | ('wsu',
37 | 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd')
38 |
39 |
40 | def iso_utc(dt=None):
41 | if dt is None:
42 | dt = datetime.utcnow()
43 | # precision only to milliseconds per WS-Security recommendation
44 | return re.sub(r'(?<=\.\d{3})\d+', '', dt.isoformat()) + 'Z'
45 |
46 |
47 | class AutoTimestamp(Timestamp):
48 |
49 | def __init__(self, validity=None):
50 | Token.__init__(self)
51 | self.validity = validity
52 |
53 | def xml(self):
54 | self.created = datetime.utcnow()
55 | root = Element("Timestamp", ns=WSUNS)
56 | created = Element('Created', ns=WSUNS)
57 | created.setText(iso_utc(self.created))
58 | root.append(created)
59 | if self.validity is not None:
60 | self.expires = self.created + timedelta(seconds=self.validity)
61 | expires = Element('Expires', ns=WSUNS)
62 | expires.setText(iso_utc(self.expires))
63 | root.append(expires)
64 | return root
65 |
66 |
67 | class AutoUsernameToken(UsernameToken):
68 |
69 | def __init__(self, username=None, password=None, setcreated=False,
70 | setnonce=False, digest=False):
71 | UsernameToken.__init__(self, username, password)
72 | self.autosetcreated = setcreated
73 | self.autosetnonce = setnonce
74 | self.digest = digest
75 |
76 | def setnonce(self, text=None):
77 | if text is None:
78 | hash = sha1()
79 | hash.update(str(random()))
80 | hash.update(iso_utc())
81 | self.nonce = hash.hexdigest()
82 | else:
83 | self.nonce = text
84 |
85 | def xml(self):
86 | if self.digest and self.password is None:
87 | raise RuntimeError("Cannot generate password digest without the password.")
88 | if self.autosetnonce:
89 | self.setnonce()
90 | if self.autosetcreated:
91 | self.setcreated()
92 | root = Element('UsernameToken', ns=WSSENS)
93 | u = Element('Username', ns=WSSENS)
94 | u.setText(self.username)
95 | root.append(u)
96 | if self.password is not None:
97 | password = self.password
98 | if self.digest:
99 | password = self.get_digest()
100 | p = Element('Password', ns=WSSENS)
101 | p.setText(password)
102 | p.set('Type', DIGEST_TYPE if self.digest else TEXT_TYPE)
103 | root.append(p)
104 | if self.nonce is not None:
105 | n = Element('Nonce', ns=WSSENS)
106 | n.setText(base64.encodestring(self.nonce)[:-1])
107 | n.set('EncodingType', BASE64_ENC_TYPE)
108 | root.append(n)
109 | if self.created:
110 | c = Element('Created', ns=WSUNS)
111 | c.setText(iso_utc(self.created))
112 | root.append(c)
113 | return root
114 |
115 | def get_digest(self):
116 | nonce = str(self.nonce) if self.nonce else ""
117 | created = iso_utc(self.created) if self.created else ""
118 | password = str(self.password)
119 | message = nonce + created + password
120 | return base64.encodestring(sha1(message).digest())[:-1]
121 |
122 |
123 | class _WsseKeywords(object):
124 |
125 | def apply_security_timestamp(self, duration=None):
126 | """Applies a Timestamp element to future requests valid for the given `duration`.
127 |
128 | The SOAP header will contain a Timestamp element as specified in the
129 | WS-Security extension. The Created and Expires values are updated
130 | every time a request is made. If `duration` is None, the Expires
131 | element will be absent.
132 |
133 | `duration` must be given in Robot Framework's time format (e.g.
134 | '1 minute', '2 min 3 s', '4.5').
135 |
136 | Example:
137 | | Apply Security Timestamp | 5 min |
138 | """
139 | if duration is not None:
140 | duration = robot.utils.timestr_to_secs(duration)
141 | wsse = self._get_wsse()
142 | wsse.tokens = [x for x in wsse.tokens if not isinstance(x, Timestamp)]
143 | wsse.tokens.insert(0, AutoTimestamp(duration))
144 | self._client().set_options(wsse=wsse)
145 |
146 | def apply_username_token(self, username, password=None, setcreated=False,
147 | setnonce=False, digest=False):
148 | """Applies a UsernameToken element to future requests.
149 |
150 | The SOAP header will contain a UsernameToken element as specified in
151 | Username Token Profile 1.1 that complies with Basic Security Profile
152 | 1.1. The Created and Nonce values, if enabled, are generated
153 | automatically and updated every time a request is made. If `digest` is
154 | True, a digest derived from the password is sent.
155 |
156 | Example:
157 | | Apply Username Token | ying | myPa$$word |
158 | """
159 | setcreated = to_bool(setcreated)
160 | setnonce = to_bool(setnonce)
161 | digest = to_bool(digest)
162 | if digest and password is None:
163 | raise RuntimeError("Password is required when digest is True.")
164 | token = AutoUsernameToken(username, password, setcreated, setnonce,
165 | digest)
166 | wsse = self._get_wsse()
167 | wsse.tokens = [x for x in wsse.tokens if not isinstance(x, UsernameToken)]
168 | wsse.tokens.append(token)
169 | self._client().set_options(wsse=wsse)
170 |
171 | # private
172 |
173 | def _get_wsse(self, create=True):
174 | wsse = self._client().options.wsse
175 | if wsse is None and create:
176 | wsse = Security()
177 | wsse.mustUnderstand = '1'
178 | return wsse
179 |
--------------------------------------------------------------------------------
/ExemploSOAPTesting/MyCustomSudsLibrary/MySudsLibrary.py:
--------------------------------------------------------------------------------
1 | # Copyright 2013 Kevin Ormbrek
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | from robot.utils import ConnectionCache
16 | from MyCustomSudsLibrary.monkeypatches import *
17 | from MyCustomSudsLibrary.factory import _FactoryKeywords
18 | from MyCustomSudsLibrary.clientmanagement import _ClientManagementKeywords
19 | from MyCustomSudsLibrary.options import _OptionsKeywords
20 | from MyCustomSudsLibrary.proxy import _ProxyKeywords
21 | from MyCustomSudsLibrary.soaplogging import _SoapLoggingKeywords
22 | from MyCustomSudsLibrary.wsse import _WsseKeywords
23 | from suds import null
24 | from robot.api import logger
25 | from robot.libraries.BuiltIn import BuiltIn
26 | import traceback
27 | import weakref
28 |
29 |
30 | class MySudsLibrary(_ClientManagementKeywords, _FactoryKeywords,
31 | _OptionsKeywords, _ProxyKeywords, _SoapLoggingKeywords,
32 | _WsseKeywords):
33 | """SudsLibrary is a library for functional testing of SOAP-based web
34 | services.
35 |
36 | SudsLibrary is based on [https://fedorahosted.org/suds/|Suds], a dynamic
37 | SOAP 1.1 client.
38 |
39 | == Case Sensitivy in SudsLibrary ==
40 | Many things in the world of SOAP are case-sensitive. This includes method
41 | names, WSDL object names and attributes, and service or port names.
42 |
43 | == Creating and Configuring a Client ==
44 | If necessary, use keywords `Bind Schema To Location` or `Add Doctor
45 | Import`. These are rarely needed. Next, `Create Soap Client` to create a Suds
46 | client. The output from this keyword contains useful information including
47 | available types and methods. Next, use other keywords to configure the
48 | client as necessary. `Set Location` is the most commonly needed keyword.
49 |
50 | == Working with WSDL Objects ==
51 | When Suds digests a WSDL, it creates dynamic types to represent the complex
52 | types defined by a WSDL or its imports. These types are listed in the
53 | output of `Create Soap Client`. WSDL objects are used as method arguments,
54 | attribute values of other WSDL objects, and return values. `Create Wsdl
55 | Object` is used to create instances of WSDL object types. To see what the
56 | structure of a WSDL object is, you can do this:
57 | | ${obj}= | Create Wsdl Object | someObject |
58 | | ${obj as str}= | Convert To String | ${obj} |
59 | | Log | ${obj as str} | |
60 | The same technique can be used to analyze a response object. It may also
61 | help to use a tool such as Eclipse or SoapUI to comprehend the structures.
62 |
63 | === Getting WSDL Object Attributes ===
64 | Getting a WSDL object's attribute value may be done with `Get Wsdl Object
65 | Attribute` or extended variable syntax*. Keywords from other libraries, such
66 | as _BuiltIn_ and _Collections_ may be used to verify attribute values.
67 | Examples:
68 | | ${name}= | Get Wsdl Object Attribute | ${person} | name |
69 | | Should Be Equal | ${person.name} | Bob | |
70 |
71 | === Setting WSDL Object Attributes ===
72 | Setting a WSDL object's attribute value may be done with `Set Wsdl Object
73 | Attribute` or extended variable syntax*. `Set Wsdl Object Attribute`
74 | verifies the argument is an object of the correct type and the attribute
75 | exists.
76 | | Set Wsdl Object Attribute | ${person} | name | Tia |
77 | | ${person.name}= | Set Variable | Tia | |
78 |
79 | * In order to use extended variable syntax, the attribute name must consist
80 | of only letters, numbers, and underscores.
81 |
82 | == Example Test ==
83 | The following simple example demonstrates verifying the return value using
84 | keywords in this library and in the `BuiltIn` and `Collections` libraries.
85 | You can run this test because it uses a public web service.
86 |
87 | | Create Soap Client | http://www.webservicex.net/Statistics.asmx?WSDL | | |
88 | | ${dbl array}= | Create Wsdl Object | ArrayOfDouble | |
89 | | Append To List | ${dbl array.double} | 2.0 | |
90 | | Append To List | ${dbl array.double} | 3.0 | |
91 | | ${result}= | Call Soap Method | GetStatistics | ${dbl array} |
92 | | Should Be Equal As Numbers | ${result.Average} | 2.5 | |
93 |
94 | The definition of type ArrayOfDouble:
95 | |
96 | |
97 | |
98 | |
99 | |
100 | Note that the attribute name on the ArrayOfDouble-type that is the list of
101 | numbers is the singular "double". Outside of the WSDL, the structure can
102 | also be seen in the output of Create Wsdl Object:
103 | | ${dbl array} = (ArrayOfDouble){
104 | | double[] =
105 | | }
106 |
107 | The relevant part of the WSDL defining the parameters to the method:
108 | |
109 | |
110 | |
111 | |
112 | |
113 | |
114 | |
115 | The definition of this method appears in the output of Create Soap Client
116 | as:
117 | | GetStatistics(ArrayOfDouble X, )
118 |
119 | == Passing Explicit NULL Values ==
120 | If you have a service that takes NULL values for required parameters or
121 | you want to pass NULL for optional object attributes, you simply need to
122 | set the value to ${SUDS_NULL}. You need to use ${SUDS_NULL} instead of
123 | ${None} because None is interpreted by the marshaller as not having a
124 | value. The soap message will contain an empty (and xsi:nil="true" if node
125 | defined as nillable). ${SUDS_NULL} is defined during library
126 | initialization, so editors like RIDE will not show it as defined.
127 |
128 | == Extending SudsLibrary ==
129 | There may be times where Suds/SudsLibrary does not work using the library
130 | keywords alone. Extending the library instead of writing a custom one will
131 | allow you to use the existing keywords in SudsLibrary.
132 |
133 | There are two methods useful for extending SudsLibrary:
134 | | _client()
135 | | _add_client(client, alias=None)
136 | The first can be used to access the current instance of
137 | suds.client.Client. The second can be used to put a client into the client
138 | cache that you have instantiated.
139 |
140 | Here is an example demonstrating how to implement a keyword that adds a
141 | MessagePlugin to the current Suds client (based on the [https://fedorahosted.org/suds/wiki/Documentation#MessagePlugin|Suds documentation]):
142 | | from robot.libraries.BuiltIn import BuiltIn
143 | | from suds.plugin import MessagePlugin
144 | |
145 | | class _MyPlugin(MessagePlugin):
146 | | def marshalled(self, context):
147 | | body = context.envelope.getChild('Body')
148 | | foo = body[0]
149 | | foo.set('id', '12345')
150 | | foo.set('version', '2.0')
151 | |
152 | | class SudsLibraryExtensions(object):
153 | | def attach_my_plugin(self):
154 | | client = BuiltIn().get_library_instance("SudsLibrary")._client()
155 | | # prepend so SudsLibrary's plugin is left in place
156 | | plugins = client.options.plugins
157 | | if any(isinstance(x, _MyPlugin) for x in plugins):
158 | | return
159 | | plugins.insert(0, _MyPlugin())
160 | | client.set_options(plugins=plugins)
161 | """
162 | def __init__(self):
163 | self._cache = ConnectionCache(no_current_msg='No current client')
164 | self._imports = []
165 | self._logger = logger
166 | self._global_timeout = True
167 | self._external_options = weakref.WeakKeyDictionary()
168 | try: # exception if Robot is not running
169 | BuiltIn().set_global_variable("${SUDS_NULL}", null())
170 | except:
171 | pass
172 |
--------------------------------------------------------------------------------
/ExemploSOAPTesting/MyCustomSudsLibrary/options.py:
--------------------------------------------------------------------------------
1 | # Copyright 2013 Kevin Ormbrek
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | from suds.xsd.doctor import Import
16 | from suds.xsd.sxbasic import Import as BasicImport
17 | from suds import ServiceNotFound
18 | from suds.transport.https import HttpAuthenticated
19 | from suds.transport.https import WindowsHttpAuthenticated
20 | from suds.transport.http import HttpAuthenticated as AlwaysSendTransport
21 | from .utils import *
22 | import robot
23 |
24 |
25 | class _OptionsKeywords(object):
26 |
27 | def set_service(self, service):
28 | """Sets the `service` to use in future requests.
29 |
30 | `service` should be the name or the index of the service as it appears in the WSDL.
31 | """
32 | service = parse_index(service)
33 | self._client().set_options(service=service)
34 |
35 | def set_port(self, port):
36 | """Sets the `port` to use in future requests.
37 |
38 | `port` should be the name or the index of the port as it appears in the WSDL.
39 | """
40 | port = parse_index(port)
41 | self._client().set_options(port=port)
42 |
43 | def set_proxies(self, *protocol_url_pairs):
44 | """Sets the http proxy settings.
45 |
46 | | Set Proxy | http | localhost:5000 | https | 10.0.4.23:80 |
47 | """
48 | if len(protocol_url_pairs) % 2 != 0:
49 | raise ValueError("There should be an even number of protocol-url pairs.")
50 | proxy = {}
51 | for i in range(0, len(protocol_url_pairs), 2):
52 | proxy[protocol_url_pairs[i]] = protocol_url_pairs[i + 1]
53 | self._client().set_options(proxy=proxy)
54 |
55 | def set_headers(self, *dict_or_key_value_pairs):
56 | """Sets _extra_ http headers to send in future requests.
57 |
58 | For HTTP headers; not to be confused with the SOAP header element.
59 |
60 | Example:
61 | | Set Headers | X-Requested-With | autogen | # using key-value pairs |
62 | or using a dictionary:
63 | | ${headers}= | Create Dictionary | X-Requested-With | autogen |
64 | | Set Headers | ${headers} | | # using a dictionary |
65 | """
66 | length = len(dict_or_key_value_pairs)
67 | if length == 1:
68 | headers = dict_or_key_value_pairs[0]
69 | elif length % 2 == 0:
70 | headers = {}
71 | for i in range(0, len(dict_or_key_value_pairs), 2):
72 | headers[dict_or_key_value_pairs[i]] = dict_or_key_value_pairs[i + 1]
73 | else:
74 | raise ValueError("There should be an even number of name-value pairs.")
75 | self._client().set_options(headers=headers)
76 |
77 | def set_soap_headers(self, *headers):
78 | """Sets SOAP headers to send in future requests.
79 |
80 | Example:
81 | | ${auth header}= | Create Wsdl Object | AuthHeader | |
82 | | Set Wsdl Object Attribute | ${auth header} | UserID | gcarlson |
83 | | Set Wsdl Object Attribute | ${auth header} | Password | heyOh |
84 | | Set Soap Headers | ${auth header} | # using WSDL object | |
85 | or using a dictionary:
86 | | ${auth dict}= | Create Dictionary | UserName | gcarlson | Password | heyOh |
87 | | Set Soap Headers | ${auth dict} | # using a dictionary | | | |
88 |
89 | For setting WS-Security elements in the SOAP header, see
90 | `Apply Username Token` and `Apply Security Timestamp`.
91 | """
92 | self._client().set_options(soapheaders=headers)
93 |
94 | def set_return_xml(self, return_xml):
95 | """Sets whether to return XML in future requests.
96 |
97 | The default value is _False_. If `return_xml` is _True_, then return
98 | the SOAP envelope as a string in future requests. Otherwise, return a
99 | Python object graph. `Get Last Received` returns the XML received
100 | regardless of this setting.
101 |
102 | See also `Call Soap Method`, `Call Soap Method Expecting Fault`, and
103 | `Specific Soap Call`.
104 |
105 | Example:
106 | | ${old value}= | Set Return Xml | True |
107 | """
108 | return_xml = to_bool(return_xml)
109 | # not using the retxml option built into Suds because Suds does not raise exceptions when a SOAP fault occurs
110 | # when retxml=True. Instead just use the XML that is already being captured with a plugin
111 | old_value = self._get_external_option("return_xml", False)
112 | self._set_external_option("return_xml", return_xml)
113 | return old_value
114 |
115 | def set_http_authentication(self, username, password, type='STANDARD'):
116 | """Sets http authentication type and credentials.
117 |
118 | Available types are STANDARD, ALWAYS_SEND, and NTLM. Type STANDARD
119 | will only send credentials to the server upon request (HTTP/1.0 401
120 | Authorization Required) by the server only. Type ALWAYS_SEND will
121 | cause an Authorization header to be sent in every request. Type NTLM
122 | is a Microsoft proprietary authentication scheme that requires the
123 | python-ntlm package to be installed, which is not packaged with Suds
124 | or SudsLibrary.
125 | """
126 | transport = self._get_transport(type, username=username, password=password)
127 | self._client().set_options(transport=transport)
128 |
129 | def set_location(self, url, service=None, names=None):
130 | """Sets location to use in future requests.
131 |
132 | This is for when the location(s) specified in the WSDL are not correct.
133 | `service` is the name or index of the service to change and ignored
134 | unless there is more than one service. `names` should be either a
135 | comma-delimited list of methods names or an iterable (e.g. a list). If
136 | no methods names are given, then sets the location for all methods of
137 | the service(s).
138 |
139 | Example:
140 | | Set Location | http://localhost:8080/myWS |
141 | """
142 | wsdl = self._client().wsdl
143 | service_count = len(wsdl.services)
144 | if (service_count == 1):
145 | service = 0
146 | elif not service is None:
147 | service = parse_index(service)
148 | if isinstance(names, bytes):
149 | names = names.split(b",")
150 | if service is None:
151 | for svc in wsdl.services:
152 | svc.setlocation(url, names)
153 | elif isinstance(service, int):
154 | wsdl.services[service].setlocation(url, names)
155 | else:
156 | for svc in wsdl.services:
157 | if svc.name == service:
158 | svc.setlocation(url, names)
159 | return
160 | raise ServiceNotFound(service)
161 |
162 | def add_doctor_import(self, import_namespace, location=None, filters=None):
163 | """Adds an import be used in the next client.
164 |
165 | Doctor imports are applied to the _next_ client created with
166 | `Create Soap Client`. Doctor imports are necessary when references are
167 | made in one schema to named objects defined in another schema without
168 | importing it. Use `location` to specify the location to download the
169 | schema file. `filters` should be either a comma-delimited list of
170 | namespaces or an iterable (e.g. a list).
171 |
172 | The following example would import the SOAP encoding schema into only
173 | the namespace http://some/namespace/A if it is not already imported:
174 | | Add Doctor Import | http://schemas.xmlsoap.org/soap/encoding/ | filters=http://some/namespace/A |
175 | """
176 | if isinstance(filters, bytes):
177 | filters = filters.split(b",")
178 | imp = Import(import_namespace, location)
179 | if not filters is None:
180 | for filter in filters:
181 | imp.filter.add(filter)
182 | self._imports.append(imp)
183 |
184 | def bind_schema_to_location(self, namespace, location):
185 | """Sets the `location` for the given `namespace` of a schema.
186 |
187 | This is for when an import statement specifies a schema but not its
188 | location. If the schemaLocation is present and incorrect, this will
189 | not override that. Bound schemas are shared amongst all instances of
190 | SudsLibrary. Schemas should be bound if necessary before `Add Doctor
191 | Import` or `Create Soap Client` where appropriate.
192 | """
193 | BasicImport.bind(namespace, location)
194 |
195 | def set_soap_timeout(self, timeout):
196 | """Sets the timeout for SOAP requests.
197 |
198 | `timeout` must be given in Robot Framework's time format (e.g.
199 | '1 minute', '2 min 3 s', '4.5'). The default timeout is 90 seconds.
200 |
201 | Example:
202 | | Set Soap Timeout | 3 min |
203 | """
204 | self._set_soap_timeout(timeout)
205 | timestr = format_robot_time(timeout)
206 | self._logger.info("SOAP timeout set to %s" % timestr)
207 |
208 | # private
209 |
210 | def _set_boolean_option(self, name, value):
211 | value = to_bool(value)
212 | self._client().set_options(**{name: value})
213 |
214 | def _set_soap_timeout(self, timeout):
215 | timeout_in_secs = robot.utils.timestr_to_secs(timeout)
216 | self._client().set_options(timeout=timeout_in_secs)
217 |
218 | def _get_external_option(self, name, default):
219 | value = default
220 | if self._client() in self._external_options:
221 | options = self._external_options[self._client()]
222 | value = options.get(name, default)
223 | return value
224 |
225 | def _set_external_option(self, name, value):
226 | if self._client() not in self._external_options:
227 | self._external_options[self._client()] = {}
228 | old_value = self._external_options[self._client()].get(name, None)
229 | self._external_options[self._client()][name] = value
230 | return old_value
231 |
232 | def _get_transport(self, auth_type, username, password):
233 | classes = {
234 | 'STANDARD': HttpAuthenticated,
235 | 'ALWAYS_SEND': AlwaysSendTransport,
236 | 'NTLM': WindowsHttpAuthenticated
237 | }
238 | try:
239 | _class = classes[auth_type.upper().strip()]
240 | except KeyError:
241 | raise ValueError("'%s' is not a supported authentication type." % auth_type)
242 | transport = _class(username=username, password=password)
243 | return transport
244 |
--------------------------------------------------------------------------------
/Exemplo Imap Library/CustomImapLibrary.py:
--------------------------------------------------------------------------------
1 | """
2 | IMAP Library - a IMAP email testing library.
3 | """
4 | import base64
5 | from email import message_from_string
6 | from imaplib import IMAP4, IMAP4_SSL
7 | from re import findall
8 | from time import sleep, time
9 | try:
10 | from urllib.request import urlopen
11 | except ImportError:
12 | from urllib2 import urlopen
13 | from builtins import str
14 |
15 |
16 | class CustomImapLibrary(object):
17 |
18 | PORT = 143
19 | PORT_SECURE = 993
20 | FOLDER = 'INBOX'
21 | ROBOT_LIBRARY_SCOPE = 'GLOBAL'
22 |
23 | def __init__(self):
24 | """ImapLibrary can be imported without argument.
25 |
26 | Examples:
27 | | = Keyword Definition = | = Description = |
28 | | Library `|` ImapLibrary | Initiate Imap library |
29 | """
30 | self._email_index = None
31 | self._imap = None
32 | self._mails = []
33 | self._mp_iter = None
34 | self._mp_msg = None
35 | self._part = None
36 |
37 | def close_mailbox(self):
38 | """Close IMAP email client session.
39 |
40 | Examples:
41 | | Close Mailbox |
42 | """
43 | self._imap.close()
44 |
45 | def delete_all_emails(self):
46 | """Delete all emails.
47 |
48 | Examples:
49 | | Delete All Emails |
50 | """
51 | typ, mails = self._imap.uid('search', None, 'ALL')
52 | self._mails = mails[0].split()
53 |
54 | print("Deleting e-mails from ID: [{0}]".format(', '.join(map(str, self._mails))))
55 |
56 | for mail in self._mails:
57 | self.delete_email(mail)
58 | self._imap.expunge()
59 |
60 | def decode_email_body(self, body_email_encoded):
61 | """Returns the email body encoded on base64 decoded to a string UTF-8.
62 |
63 | Arguments:
64 | - ``body_email_encoded``: An string from the email body encoded on base64.
65 |
66 | Examples:
67 | | BODY | Get Email Body | EMAIL_INDEX |
68 | | BODYDECODED | Decode Email Body | BODY |
69 | | Log | BODY |
70 | """
71 | print("Deconding [%s] to string." % (body_email_encoded))
72 |
73 | if not body_email_encoded.endswith("=="):
74 | body_email_encoded = body_email_encoded + "=="
75 |
76 | email_decoded = base64.b64decode(body_email_encoded)
77 |
78 | return email_decoded.decode('UTF-8')
79 |
80 | def delete_all_emails_with_kwargs(self, **kwargs):
81 | """Delete all emails.
82 |
83 | Examples:
84 | | Delete All Emails |
85 | """
86 | self._mails = self._check_emails(**kwargs)
87 |
88 | for mail in self._mails:
89 | self.delete_email(mail)
90 | self._imap.expunge()
91 |
92 | def delete_email(self, email_index):
93 | """Delete email on given ``email_index``.
94 |
95 | Arguments:
96 | - ``email_index``: An email index to identity the email message.
97 |
98 | Examples:
99 | | Delete Email | INDEX |
100 | """
101 | self._imap.uid('store', email_index, '+FLAGS', r'(\DELETED)')
102 | self._imap.expunge()
103 |
104 | def get_email_body(self, email_index):
105 | """Returns the decoded email body on multipart email message,
106 | otherwise returns the body text.
107 |
108 | Arguments:
109 | - ``email_index``: An email index to identity the email message.
110 |
111 | Examples:
112 | | Get Email Body | INDEX |
113 | """
114 | if self._is_walking_multipart(email_index):
115 | body = self.get_multipart_payload(decode=True)
116 | else:
117 | body = self._imap.uid('fetch',
118 | email_index,
119 | '(BODY[TEXT])')[1][0][1].\
120 | decode('quoted-printable')
121 | return body
122 |
123 | def get_links_from_email(self, email_index):
124 | """Returns all links found in the email body from given ``email_index``.
125 |
126 | Arguments:
127 | - ``email_index``: An email index to identity the email message.
128 |
129 | Examples:
130 | | Get Links From Email | INDEX |
131 | """
132 | body = self.get_email_body(email_index)
133 | return findall(r'href=[\'"]?([^\'" >]+)', body)
134 |
135 | def get_matches_from_email(self, email_index, pattern):
136 | """Returns all Regular Expression ``pattern`` found in the email body
137 | from given ``email_index``.
138 |
139 | Arguments:
140 | - ``email_index``: An email index to identity the email message.
141 | - ``pattern``: It consists of one or more character literals, operators, or constructs.
142 |
143 | Examples:
144 | | Get Matches From Email | INDEX | PATTERN |
145 | """
146 | body = self.get_email_body(email_index)
147 | return findall(pattern, body)
148 |
149 | def get_multipart_content_type(self):
150 | """Returns the content type of current part of selected multipart email message.
151 |
152 | Examples:
153 | | Get Multipart Content Type |
154 | """
155 | return self._part.get_content_type()
156 |
157 | def get_multipart_field(self, field):
158 | """Returns the value of given header ``field`` name.
159 |
160 | Arguments:
161 | - ``field``: A header field name: ``From``, ``To``, ``Subject``, ``Date``, etc.
162 | All available header field names of an email message can be found by running
163 | `Get Multipart Field Names` keyword.
164 |
165 | Examples:
166 | | Get Multipart Field | Subject |
167 | """
168 | return self._mp_msg[field]
169 |
170 | def get_multipart_field_names(self):
171 | """Returns all available header field names of selected multipart email message.
172 |
173 | Examples:
174 | | Get Multipart Field Names |
175 | """
176 | return list(self._mp_msg.keys())
177 |
178 | def get_multipart_payload(self, decode=False):
179 | """Returns the payload of current part of selected multipart email message.
180 |
181 | Arguments:
182 | - ``decode``: An indicator flag to decode the email message. (Default False)
183 |
184 | Examples:
185 | | Get Multipart Payload |
186 | | Get Multipart Payload | decode=True |
187 | """
188 | payload = self._part.get_payload(decode=decode)
189 | charset = self._part.get_content_charset()
190 | if charset is not None:
191 | return payload.decode(charset)
192 | return payload
193 |
194 | def mark_all_emails_as_read(self):
195 | """Mark all received emails as read.
196 |
197 | Examples:
198 | | Mark All Emails As Read |
199 | """
200 | for mail in self._mails:
201 | self._imap.uid('store', mail, '+FLAGS', r'\SEEN')
202 |
203 | def mark_as_read(self):
204 | """****DEPRECATED****
205 | Shortcut to `Mark All Emails As Read`.
206 | """
207 | self.mark_all_emails_as_read()
208 |
209 | def mark_email_as_read(self, email_index):
210 | """Mark email on given ``email_index`` as read.
211 |
212 | Arguments:
213 | - ``email_index``: An email index to identity the email message.
214 |
215 | Examples:
216 | | Mark Email As Read | INDEX |
217 | """
218 | self._imap.uid('store', email_index, '+FLAGS', r'\SEEN')
219 |
220 | def open_link_from_email(self, email_index, link_index=0):
221 | """Open link URL from given ``link_index`` in email message body of given ``email_index``.
222 | Returns HTML content of opened link URL.
223 |
224 | Arguments:
225 | - ``email_index``: An email index to identity the email message.
226 | - ``link_index``: The link index to be open. (Default 0)
227 |
228 | Examples:
229 | | Open Link From Email |
230 | | Open Link From Email | 1 |
231 | """
232 | urls = self.get_links_from_email(email_index)
233 |
234 | if len(urls) > link_index:
235 | resp = urlopen(urls[link_index])
236 | content_type = resp.headers.getheader('content-type')
237 | if content_type:
238 | enc = content_type.split('charset=')[-1]
239 | return str(resp.read(), enc)
240 | else:
241 | return resp.read()
242 | else:
243 | raise AssertionError("Link number %i not found!" % link_index)
244 |
245 | def open_link_from_mail(self, email_index, link_index=0):
246 | """****DEPRECATED****
247 | Shortcut to `Open Link From Email`.
248 | """
249 | return self.open_link_from_email(email_index, link_index)
250 |
251 | def open_mailbox(self, **kwargs):
252 | """Open IMAP email client session to given ``host`` with given ``user`` and ``password``.
253 |
254 | Arguments:
255 | - ``host``: The IMAP host server. (Default None)
256 | - ``is_secure``: An indicator flag to connect to IMAP host securely or not. (Default True)
257 | - ``password``: The plaintext password to be use to authenticate mailbox on given ``host``.
258 | - ``port``: The IMAP port number. (Default None)
259 | - ``user``: The username to be use to authenticate mailbox on given ``host``.
260 | - ``folder``: The email folder to read from. (Default INBOX)
261 |
262 | Examples:
263 | | Open Mailbox | host=HOST | user=USER | password=SECRET |
264 | | Open Mailbox | host=HOST | user=USER | password=SECRET | is_secure=False |
265 | | Open Mailbox | host=HOST | user=USER | password=SECRET | port=8000 |
266 | | Open Mailbox | host=HOST | user=USER | password=SECRET | folder=Drafts
267 | """
268 | host = kwargs.pop('host', kwargs.pop('server', None))
269 | is_secure = kwargs.pop('is_secure', 'True') == 'True'
270 | port = int(kwargs.pop('port', self.PORT_SECURE if is_secure else self.PORT))
271 | folder = '"%s"' % str(kwargs.pop('folder', self.FOLDER))
272 | self._imap = IMAP4_SSL(host, port) if is_secure else IMAP4(host, port)
273 | self._imap.login(kwargs.pop('user', None), kwargs.pop('password', None))
274 | self._imap.select(folder)
275 | self._init_multipart_walk()
276 |
277 | def wait_for_email(self, **kwargs):
278 | """Wait for email message to arrived base on any given filter criteria.
279 | Returns email index of the latest email message received.
280 |
281 | Arguments:
282 | - ``poll_frequency``: The delay value in seconds to retry the mailbox check. (Default 10)
283 | - ``recipient``: Email recipient. (Default None)
284 | - ``sender``: Email sender. (Default None)
285 | - ``status``: A mailbox status filter: ``MESSAGES``, ``RECENT``, ``UIDNEXT``,
286 | ``UIDVALIDITY``, and ``UNSEEN``.
287 | Please see [https://goo.gl/3KKHoY|Mailbox Status] for more information.
288 | (Default None)
289 | - ``subject``: Email subject. (Default None)
290 | - ``text``: Email body text. (Default None)
291 | - ``timeout``: The maximum value in seconds to wait for email message to arrived.
292 | (Default 60)
293 | - ``folder``: The email folder to check for emails. (Default INBOX)
294 |
295 | Examples:
296 | | Wait For Email | sender=noreply@domain.com |
297 | | Wait For Email | sender=noreply@domain.com | folder=OUTBOX
298 | """
299 | poll_frequency = float(kwargs.pop('poll_frequency', 10))
300 | timeout = int(kwargs.pop('timeout', 60))
301 | end_time = time() + timeout
302 | while time() < end_time:
303 | self._mails = self._check_emails(**kwargs)
304 | if len(self._mails) > 0:
305 | return self._mails[-1]
306 | if time() < end_time:
307 | sleep(poll_frequency)
308 | raise AssertionError("No email received within %ss" % timeout)
309 |
310 | def wait_for_mail(self, **kwargs):
311 | """****DEPRECATED****
312 | Shortcut to `Wait For Email`.
313 | """
314 | return self.wait_for_email(**kwargs)
315 |
316 | def walk_multipart_email(self, email_index):
317 | """Returns total parts of a multipart email message on given ``email_index``.
318 | Email message is cache internally to be used by other multipart keywords:
319 | `Get Multipart Content Type`, `Get Multipart Field`, `Get Multipart Field Names`,
320 | `Get Multipart Field`, and `Get Multipart Payload`.
321 |
322 | Arguments:
323 | - ``email_index``: An email index to identity the email message.
324 |
325 | Examples:
326 | | Walk Multipart Email | INDEX |
327 | """
328 | if not self._is_walking_multipart(email_index):
329 | data = self._imap.uid('fetch', email_index, '(RFC822)')[1][0][1]
330 | msg = message_from_string(data)
331 | self._start_multipart_walk(email_index, msg)
332 | try:
333 | self._part = next(self._mp_iter)
334 | except StopIteration:
335 | self._init_multipart_walk()
336 | return False
337 | # return number of parts
338 | return len(self._mp_msg.get_payload())
339 |
340 | def _check_emails(self, **kwargs):
341 | """Returns filtered email."""
342 | folder = '"%s"' % str(kwargs.pop('folder', self.FOLDER))
343 | criteria = self._criteria(**kwargs)
344 | # Calling select before each search is necessary with gmail
345 | status, data = self._imap.select(folder)
346 | if status != 'OK':
347 | raise Exception("imap.select error: %s, %s" % (status, data))
348 | typ, msgnums = self._imap.uid('search', None, *criteria)
349 | if typ != 'OK':
350 | raise Exception('imap.search error: %s, %s, criteria=%s' % (typ, msgnums, criteria))
351 | return msgnums[0].split()
352 |
353 | @staticmethod
354 | def _criteria(**kwargs):
355 | """Returns email criteria."""
356 | criteria = []
357 | recipient = kwargs.pop('recipient', kwargs.pop('to_email', kwargs.pop('toEmail', None)))
358 | sender = kwargs.pop('sender', kwargs.pop('from_email', kwargs.pop('fromEmail', None)))
359 | status = kwargs.pop('status', None)
360 | subject = kwargs.pop('subject', None)
361 | text = kwargs.pop('text', None)
362 | if recipient:
363 | criteria += ['TO', '"%s"' % recipient]
364 | if sender:
365 | criteria += ['FROM', '"%s"' % sender]
366 | if subject:
367 | criteria += ['SUBJECT', '"%s"' % subject]
368 | if text:
369 | criteria += ['TEXT', '"%s"' % text]
370 | if status:
371 | criteria += [status]
372 | if not criteria:
373 | criteria = ['UNSEEN']
374 | return criteria
375 |
376 | def _init_multipart_walk(self):
377 | """Initialize multipart email walk."""
378 | self._email_index = None
379 | self._mp_msg = None
380 | self._part = None
381 |
382 | def _is_walking_multipart(self, email_index):
383 | """Returns boolean value whether the multipart email walk is in-progress or not."""
384 | return self._mp_msg is not None and self._email_index == email_index
385 |
386 | def _start_multipart_walk(self, email_index, msg):
387 | """Start multipart email walk."""
388 | self._email_index = email_index
389 | self._mp_msg = msg
390 | self._mp_iter = msg.walk()
391 |
--------------------------------------------------------------------------------
/RabbitMQ/RabbitMqCustom.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from robot.api import logger
4 | from robot.utils import ConnectionCache
5 | import http.client
6 | import base64
7 | import json
8 | import socket
9 | import urllib.parse
10 | import urllib
11 |
12 |
13 | class RabbitMqCustom(object):
14 | """
15 | Library for managing the server RabbitMq.
16 |
17 | == Example ==
18 | | *Settings* | *Value* |
19 | | Library | RabbitMqManager |
20 | | Library | Collections |
21 |
22 | | *Test Cases* | *Action* | *Argument* | *Argument* | *Argument* | *Argument* | *Argument* |
23 | | Simple |
24 | | | Connect To Rabbitmq | my_host_name | 15672 | guest | guest | alias=rmq |
25 | | | ${overview}= | Overview |
26 | | | Log Dictionary | ${overview} |
27 | | | Close All Rabbitmq Connections |
28 | """
29 |
30 | ROBOT_LIBRARY_SCOPE = 'GLOBAL'
31 |
32 | def __init__(self):
33 | self._connection = None
34 | self.headers = None
35 | self._cache = ConnectionCache()
36 |
37 | def connect_to_rabbitmq(self, host, port, username='guest', password='guest', timeout=15, alias=None):
38 | """
39 | Connecting to the server RabbitMq.
40 |
41 | *Args:*\n
42 | _host_ - server name;\n
43 | _port_ - port number;\n
44 | _username_ - is the name of the user;\n
45 | _password_ - is the user password;\n
46 | _timeout_ - connection timeout;\n
47 | _alias_ - connection alias;\n
48 |
49 | *Returns:*\n
50 | The index of the current connection.
51 |
52 | *Raises:*\n
53 | socket.error if you can not create a connection.
54 |
55 | *Example:*\n
56 | | Connect To Rabbitmq | my_host_name | 15672 | guest | guest | alias=rmq |
57 | """
58 |
59 | port = int(port)
60 | timeout = int(timeout)
61 | logger.debug('Connecting using : host=%s, port=%d, username=%s, password=%s, timeout=%d, alias=%s ' % (
62 | host, port, username, password, timeout, alias))
63 | self.headers = {"Authorization": b"Basic " +
64 | base64.b64encode(username.encode() + b":" + password.encode())}
65 | logger.debug(self.headers)
66 | try:
67 | self._connection = http.client.HTTPConnection(host, port, timeout)
68 | self._connection.connect()
69 | return self._cache.register(self._connection, alias)
70 | except socket.error as e:
71 | raise Exception("Could not connect to RabbitMq", str(e))
72 |
73 | def switch_rabbitmq_connection(self, index_or_alias):
74 | """
75 | Switch between active connections with RabbitMq, using their index or alias..
76 |
77 | The alias is specified in the keyword [#Connect To Rabbitmq|Connect To Rabbitmq], which also returns the connection index.
78 |
79 | *Args:*\n
80 | _index_or_alias_ - index of a connection or its alias;
81 |
82 | *Returns:*\n
83 | Index of the previous connection..
84 |
85 | *Example:*\n
86 | | Connect To Rabbitmq | my_host_name_1 | 15672 | guest | guest | alias=rmq1 |
87 | | Connect To Rabbitmq | my_host_name_2 | 15672 | guest | guest | alias=rmq2 |
88 | | Switch Rabbitmq Connection | rmq1 |
89 | | ${live}= | Is alive |
90 | | Switch Rabbitmq Connection | rmq2 |
91 | | ${live}= | Is alive |
92 | | Close All Rabbitmq Connections |
93 | """
94 |
95 | old_index = self._cache.current_index
96 | self._connection = self._cache.switch(index_or_alias)
97 | return old_index
98 |
99 | def disconnect_from_rabbitmq(self):
100 | """
101 | Closing the current connection to RabbitMq.
102 |
103 | *Example:*\n
104 | | Connect To Rabbitmq | my_host_name | 15672 | guest | guest | alias=rmq |
105 | | Disconnect From Rabbitmq |
106 | """
107 |
108 | logger.debug('Close connection with : host=%s, port=%d ' %
109 | (self._connection.host, self._connection.port))
110 | self._connection.close()
111 |
112 | def close_all_rabbitmq_connections(self):
113 | """
114 | Closing all connections from RabbitMq..
115 |
116 | This keyword is used to close all connections in the event that several of them were opened.
117 | Use [#Disconnect From Rabbitmq|Disconnect From Rabbitmq] и [#Close All Rabbitmq Connections|Close All Rabbitmq Connections]
118 | together it is impossible..
119 |
120 | After this keyword is executed, the index returned by [#Connect To Rabbitmq|Connect To Rabbitmq], starts at 1.
121 |
122 | *Example:*\n
123 | | Connect To Rabbitmq | my_host_name | 15672 | guest | guest | alias=rmq |
124 | | Close All Rabbitmq Connections |
125 | """
126 |
127 | self._connection = self._cache.close_all()
128 |
129 | def _http_request(self, method, path, body):
130 | """
131 | Querying for RabbitMq
132 |
133 | *Args:*\n
134 | _method_ - query method;\n
135 | _path_ - uri request;\n
136 | _body_ - body POST request;\n
137 | """
138 |
139 | if body != "":
140 | self.headers["Content-Type"] = "application/json"
141 |
142 | logger.debug('Prepared request with method ' + method + ' to ' + 'http://' +
143 | self._connection.host + ':' + str(self._connection.port) + path + ' and body\n' + body)
144 |
145 | try:
146 | # TODO: analiser o funcionamento do cache de conexão
147 | # precisa recriar a toda hora?
148 | self._connection = http.client.HTTPConnection(
149 | self._connection.host, self._connection.port,
150 | self._connection.timeout)
151 | self._connection.connect()
152 |
153 | self._connection.request(method, path, body, self.headers)
154 | except socket.error as e:
155 | raise Exception("Could not send request: {0}".format(e))
156 |
157 | resp = self._connection.getresponse()
158 | s = resp.read()
159 |
160 | if resp.status == 400:
161 | raise Exception(json.loads(s))
162 | if resp.status == 401:
163 | raise Exception("Access refused: {0}".format(
164 | 'http://' + self._connection.host + ':' + str(self._connection.port) + path))
165 | if resp.status == 404:
166 | raise Exception("Not found: {0}".format(
167 | 'http://' + self._connection.host + ':' + str(self._connection.port) + path))
168 | if resp.status == 301:
169 | url = urllib.parse.urlparse(resp.getheader('location'))
170 | raise Exception(url)
171 | [host, port] = url.netloc.split(':')
172 | self.options.hostname = host
173 | self.options.port = int(port)
174 | return self.http(method, url.path + '?' + url.query, body)
175 | if resp.status < 200 or resp.status > 400:
176 | raise Exception("Received %d %s for request %s\n%s"
177 | % (resp.status, resp.reason, 'http://' + self._connection.host + ':' + str(self._connection.port) + path, resp.read()))
178 | return s
179 |
180 | def _get(self, path):
181 | return self._http_request('GET', '/api%s' % path, '')
182 |
183 | def _put(self, path, body):
184 | print("/api%s" % path)
185 | return self._http_request("PUT", "/api%s" % path, body)
186 |
187 | def _post(self, path, body):
188 | return self._http_request("POST", "/api%s" % path, body)
189 |
190 | def _delete(self, path):
191 | return self._http_request("DELETE", "/api%s" % path, "")
192 |
193 | def _quote_vhost(self, vhost):
194 | """
195 | Decodificação vhost.
196 | """
197 |
198 | if vhost == '/':
199 | vhost = '%2F'
200 | if vhost != '%2F':
201 | vhost = urllib.parse.quote(vhost)
202 | return vhost
203 |
204 | def is_alive(self):
205 | """
206 | RabbitMq health check..
207 |
208 | The GET request is sent as follows: 'http://:/api/' and the return code is checked.
209 |
210 | *Returns:*\n
211 | bool True, if the return code is 200.\n
212 | bool False in all other cases.
213 |
214 | *Raises:*\n
215 | socket.error in case it is unreasonable to send a GET request.
216 |
217 | *Example:*\n
218 | | ${live}= | Is Alive |
219 | =>\n
220 | True
221 | """
222 |
223 | try:
224 | self._get('/cluster-name')
225 | except Exception:
226 | return False
227 |
228 | return True
229 |
230 | def overview(self):
231 | """
232 | Information about the server RabbitMq.
233 |
234 | *Returns:*\n
235 | Dictionary with information about the server.
236 |
237 | *Example:*\n
238 | | ${overview}= | Overview |
239 | | Log Dictionary | ${overview} |
240 | | ${version}= | Get From Dictionary | ${overview} | rabbitmq_version |
241 | =>\n
242 | Dictionary size is 13 and it contains following items:
243 | | erlang_full_version | Erlang R16B02 (erts-5.10.3) [source] [64-bit] [smp:2:2] [async-threads:30] [hipe] [kernel-poll:true] |
244 | | erlang_version | R16B02 |
245 | | listeners | [{u'node': u'rabbit@srv2-rs582b-m', u'ip_address': u'0.0.0.0', u'protocol': u'amqp', u'port': 5672}] |
246 | | management_version | 3.6.6 |
247 | | message_stats | [] |
248 |
249 | ${version} = 3.6.6
250 | """
251 |
252 | return json.loads(self._get('/overview'))
253 |
254 | def connections(self):
255 | """
256 | A list of open connections..
257 | """
258 |
259 | return json.loads(self._get('/connections'))
260 |
261 | def get_name_of_all_connections(self):
262 | """
263 | A list of the names of all open connections.
264 | """
265 |
266 | names = []
267 | data = self.connections()
268 | for item in data:
269 | names.append(item['name'])
270 | return names
271 |
272 | def channels(self):
273 | """
274 | List of open channels.
275 | """
276 |
277 | return json.loads(self._get('/channels'))
278 |
279 | def exchanges(self):
280 | """
281 | Exchange list.
282 |
283 | *Example:*\n
284 | | ${exchanges}= | Exchanges |
285 | | Log List | ${exchanges} |
286 | | ${item}= | Get From list | ${exchanges} | 1 |
287 | | ${name}= | Get From Dictionary | ${q} | name |
288 | =>\n
289 | List length is 8 and it contains following items:
290 | | 0 | {u'name': u'', u'durable': True, u'vhost': u'/', u'internal': False, u'message_stats': [], u'arguments': {}, u'type': u'direct', u'auto_delete': False} |
291 | | 1 | {u'name': u'amq.direct', u'durable': True, u'vhost': u'/', u'internal': False, u'message_stats': [], u'arguments': {}, u'type': u'direct', u'auto_delete': False} |
292 | ...\n
293 | ${name} = amq.direct
294 | """
295 |
296 | return json.loads(self._get('/exchanges'))
297 |
298 | def get_names_of_all_exchanges(self):
299 | """
300 | List of names of all exchanges.
301 |
302 | *Example:*\n
303 | | ${names}= | Get Names Of All Exchanges |
304 | | Log List | ${names} |
305 | =>\n
306 | | List has one item:
307 | | amq.direct
308 | """
309 |
310 | names = []
311 | data = self.exchanges()
312 | for item in data:
313 | names.append(item['name'])
314 | return names
315 |
316 | def queues(self):
317 | """
318 | List of queues.
319 | """
320 |
321 | return json.loads(self._get('/queues'))
322 |
323 | def get_queues_on_vhost(self, vhost='%2F'):
324 | """
325 | List of queues for the virtual host.
326 |
327 | *Args:*\n
328 | _vhost_ -the name of the virtual host (recoded using urllib.parse.quote)
329 | """
330 |
331 | return json.loads(self._get('/queues/' + self._quote_vhost(vhost)))
332 |
333 | def get_queue(self, name, vhost='%2F'):
334 | """
335 | List of queues for the virtual host.
336 |
337 | *Args:*\n
338 | _queue_name_ - queue name;\n
339 | _vhost_ - the name of the virtual host (recoded using urllib.parse.quote)
340 | """
341 |
342 | return json.loads(self._get('/queues/' + self._quote_vhost(vhost) + '/' + urllib.parse.quote(name)))
343 |
344 | def get_names_of_queues_on_vhost(self, vhost='%2F'):
345 | """
346 | List of virtual host queue names.
347 |
348 | *Args:*\n
349 | - vhost: the name of the virtual host (recoded using urllib.parse.quote)
350 |
351 | *Example:*\n
352 | | ${names}= | Get Names Of Queues On Vhost |
353 | | Log List | ${names} |
354 | =>\n
355 | | List has one item:
356 | | federation: ex2 -> rabbit@server.br
357 | """
358 | names = []
359 | data = self.get_queues_on_vhost(vhost)
360 | for item in data:
361 | names.append(item['name'])
362 | return names
363 |
364 | def queue_exists(self, queue, vhost='%2F'):
365 | """
366 | Verifies that the one or more queues exists
367 | """
368 | names = self.get_names_of_queues_on_vhost()
369 | if queue in names:
370 | return True
371 | else:
372 | return False
373 |
374 | def delete_queues_by_name(self, name, vhost='%2F'):
375 | """
376 | Remove the queue from the virtual host.
377 |
378 | *Args:*\n
379 | _name_ - is the name of the queue;\n
380 | _vhost_ - is the name of the virtual host;\n
381 | """
382 | print('Deletando a fila: %s' % (name))
383 | return self._delete('/queues/' + self._quote_vhost(vhost) + '/' + urllib.parse.quote(name))
384 |
385 | def vhosts(self):
386 | """
387 | List of virtual hosts.
388 | """
389 | return json.loads(self._get('/vhosts'))
390 |
391 | def nodes(self):
392 | """
393 | List of nodes in the RabbitMQ cluster
394 | """
395 | return json.loads(self._get('/nodes'))
396 |
397 | @property
398 | def _cluster_name(self):
399 | """
400 | Name identifying this RabbitMQ cluster.
401 | """
402 | return json.loads(self._get('/cluster-name'))
403 |
404 | def create_queues_by_name(self, name, auto_delete=False, durable=True, arguments={}, vhost='%2F'):
405 | """
406 | Create an individual queue.
407 | """
408 | print('Criando a fila: %s' % (name))
409 | node = self._cluster_name['name']
410 | body = json.dumps({
411 | "auto_delete": auto_delete,
412 | "durable": "true",
413 | "arguments": arguments,
414 | "node": node
415 | })
416 | print("Body: %s" % body)
417 | print('/queues/' + self._quote_vhost(vhost) + '/' + urllib.parse.quote(name))
418 | return self._put('/queues/' + self._quote_vhost(vhost) + '/' + urllib.parse.quote(name), body=body)
419 |
420 | def publish_message_by_name(self, queue, msg, properties, vhost='%2F'):
421 | """
422 | Publish a message to a given exchange
423 | """
424 |
425 | name = "amq.default"
426 | body = json.dumps({
427 | "properties": properties,
428 | "routing_key": queue,
429 | "payload": msg,
430 | "payload_encoding": "string"
431 | })
432 | routed = self._post('/exchanges/' + self._quote_vhost(vhost) +
433 | '/' + urllib.parse.quote(name) + '/publish', body=body)
434 | print("Body Enviado: %s" % body)
435 | print("Fila Publicada: %s" % queue)
436 | return json.loads(routed)
437 |
438 | def get_messages_by_queue(self, queue, count=5, requeue=False, encoding="auto", truncate=2000000, vhost='%2F'):
439 | """
440 | Get messages from a queue.
441 | """
442 |
443 | print('Pegando %s mensagens da fila: %s' % (count, queue))
444 | body = json.dumps({
445 | "count":
446 | count,
447 | "requeue":
448 | requeue,
449 | "encoding":
450 | encoding,
451 | "truncate":
452 | truncate,
453 | "ackmode":
454 | "ack_requeue_true" if requeue else "ack_requeue_false"
455 | })
456 | messages = self._post('/queues/' + self._quote_vhost(vhost) +
457 | '/' + urllib.parse.quote(queue) + '/get', body=body)
458 | return json.loads(messages)
459 |
460 | def purge_messages_by_queue(self, name, vhost='%2F'):
461 | """
462 | Purge contents of a queue.
463 | """
464 | print('Apagando as mensagens da fila: %s' % (name))
465 | return self._delete('/queues/' + self._quote_vhost(vhost) + '/' + urllib.parse.quote(name) + '/contents')
466 |
--------------------------------------------------------------------------------