Pesquisar este blog

segunda-feira, 29 de maio de 2017

Enviando comandos para qualquer aplicativo através do Ruby.


Muitas das vezes estamos trabalhando com automação de testes e precisamos enviar um determinado comando para um aplicativo e não funciona corretamente, temos uma segunda opção pelo Wscript.Shell que é um objeto que permite acesso direto ao shell do Windows, através do método SendKeys podemos enviar comandos do Windows.


# Require the win32ole library:
require 'win32ole'

'
To maximixe the active window "% x" (Alt+SpaceBar, x)
To minimize the active window "% n" (Alt+SpaceBar, n)
To restore the active window "% r" (Alt+SpaceBar, r)
To close window "%{F4}"
# ALT+A --> wsh.SendKeys("%a")

# ENTER --> wsh.SendKeys("{ENTER}")
Temos uma lista de comandos no site da microsoft abaixo:
 https://msdn.microsoft.com/en-us/library/8c6yea83.aspx
'

# Cria a instancia do Wscript Shell, para poder usar os metodos.
wsh = WIN32OLE.new('Wscript.Shell')

# Passar o Nome da Janela atual
if wsh.AppActivate('*new 3 - Notepad++')
  # Tempo de espera em segundos
  sleep(1)
  # comando SendKeys para enviar o comando
  wsh.SendKeys("% x")
end



----------------------------------------------------------
KeySpecial Character
  SHIFT+
  CTRL^
  ALT%
----------------------------------------------------------

terça-feira, 25 de abril de 2017

Como corrigir no Ruby certificate verify failed



Erro no SSL certificado, o erro é devido você ter um certificado antigo, que não é mais válido.

1. Abra o cmd e digite os comandos abaixo:
gem which rubygems

# Dê um start dentro da pasta rubygems, mude para o caminho correto da sua versão:
start C:\Ruby23\lib\ruby\2.3.0\rubygems

1.2. Agora devemos copiar o certificado para a pasta ssl_certs, o meu caminho abaixo é esse dependendo da versão o caminho muda, ou seja atualize o caminho do ssl_certs abaixo:

Link do Certificado:

# deve baixa o certificado no link acime e colocar nessa pasta:
C:\Ruby23\lib\ruby\2.3.0\rubygems\ssl_certs

Feche o cmd e abra novamente e agora deve funcionar.


2) Se você está precisando somente Instalar a gem, sem resolver o problema, basta instalar a gem apontando somente o http sem mudar o anterior.

gem install rails --source http://rubygems.org


3)  A terceira forma é Mudar o endereço https pelo http, ou você pode adicionar as duas.

gem source -a http://rubygems.org/
gem source --update
gem source -r https://rubygems.org/

# os comandos são
# adicionar -a/--add
# remover -r/--remove
# lista os sites -l/--list

gem sources --add http://rubygems.org
gem sources --remove https://rubygems.org
gem sources --list
gem source --update


** Observação fechar o cmd do windows e abra novamente para instalar.

No MAC e no Linux:
Baixe o certificado no site: http://curl.haxx.se/ca/cacert.pem
E depois copie e replace o certificado atual no caminho:
/usr/local/etc/openssl/cert.pem.
E por fim adicione ao path:
export SSL_CERT_FILE=/usr/local/etc/openssl/cert.pem

Você pode instalar pelo Homebrew (precisa instalar ele primeiro):
brew update
brew install openssl
brew link openssl --force
brew install curl-ca-bundle


Referências:
https://gist.github.com/fnichol/867550 
https://railsapps.github.io/openssl-certificate-verify-failed.html
https://stackoverflow.com/questions/20399531/how-to-tell-gem-command-not-to-use-ssl

sábado, 11 de fevereiro de 2017

Resolvendo problemas de versões antigas e novas do Selenium com Gradle + Java



        Faz tempo que não escrevo um Post pra Galera de testes, vou falar sobre um problema que tive recentemente com um Projeto em Java, dessa inúmeras atualizações do Selenium versões antigas de Browsers deixaram de funcionar.

     Agora você é obrigado a fazer o marionete no Firefox, como me deram a missão de rodar o Selenium em algumas versões do Linux como o Debian, Canaima, essas versões de OS demoram atualizar os Browsers por segurança, tentei atualizar o sistema operacional, mas não funcionou como esperado.

     Procurei outras soluções e pensei como o Gradle é um gerenciado de dependências ou melhor build automation system, deve ter uma maneira de fazer através dele, como não tinha muito tempo pra resolver esse problema consultei um amigo o Gabriel que já trabalhou bastante com java, me sugeriu a seguinte solução.


/*
build.gradle file for building and running Selenium tests
Example uses:
gradle clean test - Rebuild and run tests
gradle test - Run tests only
gradle cleanTest test   - Force tests to be run even if up to date
gradle viewResults - Displays the report of test results (Windows only)
*/

// Support for building and testing
apply plugin: 'java'

// (Optional) configure name and version for jar
jar {
version  '1.0'
baseName 'SeleniumStarter'
extension '.jar'
}

// Cf. Maven properties
ext.junitVersion = '4.11'
ext.seleniumVersion = '2.41.0'


// Cf. Maven <dependencies>
dependencies {
compile group: 'junit', name: 'junit', version: junitVersion
compile group: 'org.seleniumhq.selenium', name: 'selenium-firefox-driver', version:seleniumVersion
    compile group: 'org.seleniumhq.selenium', name: 'selenium-chrome-driver', version:seleniumVersion
compile group: 'org.seleniumhq.selenium', name: 'selenium-api', version:seleniumVersion
compile group: 'org.seleniumhq.selenium', name: 'selenium-java', version:seleniumVersion
}

// A custom task to show report on tests that have run
task viewResults(dependsOn: ['test'] , type:Exec) {
workingDir './build/reports/tests'
commandLine 'cmd', '/c', 'start index.html'
}

// Resolve Maven dependencies as Maven does
repositories {
mavenCentral()
mavenLocal()
}

Temos o exemplo do build.gradle acima ele vai baixar as dependências com um versão especifica, ou seja toda vez que for rodar os testes precisa mudar a versão da dependência, nem todo mundo no projeto vai lembrar disso, uns trabalhando no windows outros no linux e são vários commits pra o branch principal. Resumindo isso vai gerar confusão.

Pra ficar melhor vamos separar as dependências antigas e novas, pra isso vamos criar dois arquivos abaixo, colocando as dependencias do Selenium 2 no antigo e as novas do 3 em dependencias.gradle:
dependencies.gradle
dependencies-old.gradle

No arquivo build.gradle, colocamos o código abaixo:

if (project.hasProperty('old')) {
  println "old"
  apply from: '${rootDir}/dependencies-old.gradle'
} else {
  println "new"
  apply from: '${rootDir}/dependencies.gradle'
}

Para rodar agora no Debian e Canaima vamos usar a opção -Pold
Comando no linux:
sudo ./gradlew -Pold -Dcucumber="--tags @feature_login" test


Não esquecendo que quando instanciar o browser você precisa tratar o antigo e novo, devido que no antigo não precisamos do marionete ficaria somente WebDriver driver = new FirefoxDriver().

No Chromium você precisa passar o comando "--no-sandbox" pra rodar como sudo, se não rodar como sudo vai dar erro nos drivers:

ChromeOptions options = new ChromeOptions();
options.addArguments("--no-sandbox");
driver = new ChromeDriver(options); 

Ainda dar para fazer melhor pegar a versão do SO e aplicar sozinho, mas vamos deixar isso para o outro POST. Espero que tenham gostado da solução simples, talvez tenha outras soluções, mas essa funcionou bem e foi bem rápido implementar.


Fontes:
[1] http://codesolid.com/using-gradle-to-build-java-selenium-projects/
[2] http://www.seleniumhq.org/docs/03_webdriver.jsp
[3] http://stackoverflow.com/questions/29540320/unable-to-execute-nightwatch-tests-on-chrome-using-linux

terça-feira, 20 de setembro de 2016

Multiplataform Hyper-V Manager using Python and FreeRDP

HYPY - HYper-v in PYthon

Multiplataform Hyper-V Manager using Python and FreeRDP

How HYPY works?

Hypy uses winrm to comunicate with hyper-v server shell and sends powershell commands to interact with the virtual machines. Using Powershell, HYPY can get Name, ID and state of virtual machines. Therefore, HYPY call freeRDP with vm-id and credentials, using settings in .conf file to connect the vm.

Pre-requisites

WinRM 

 

Hypy uses winrm to communicate with the hyper-v host, so it must be enabled and accepting connections. https://github.com/diyan/pywinrm has a session explaining how to Enable WinRM on the remote host.

FreeRDP

 

FreeRDP binary must be in path (windows, linux and mac). Make sure FreeRDP is working before using hypy or it will not open the session to the virtual machine. If you are using Linux, you package manager should have freerdp avaiable or look into https://github.com/FreeRDP/FreeRDP for install instructions.

Configuration

To configure Hypy, change the file 'hypy.conf'
[credentials]
host = <server name in domain>
domain = <domain name>
user = <user name in server>
pass = <password>

[options]
cache_file = <name of cache file>
sync_interval = <interval in hours to make new cache file>
You must have write permissions to the path pointed by cache_file

usage

If you don't know how to use hypy, you can use hypy.py --help
hypy.py --help
  Usage: hypy.py [OPTIONS] COMMAND [ARGS]...

  Multiplataform Hyper-V Manager using Python and FreeRDP

Options:
  --help  Show this message and exit.

Commands:
  connect  Connect to virtual machine identified by...
  create   Create a new snapshot with vm's current state
  delete   Delete a machine's snapshot by name
  list     List virtual machines and its indexes
  pause    Pause virtual machine identified by index
  restore  Restore virtual machine snapshot
  resume   Resume (paused) virtual machine identified by...
  snaps    List virtual machine snapshots
  start    Start virtual machine identified by index
  stop     Stop virtual machine identified by index
 
If you need help on any subcommand, run hypy.py COMMAND --help

Autor: Gabriel Avanzi. 
https://github.com/avanzzzi/hypy

domingo, 21 de agosto de 2016

Criando uma Mini-Interface para Execução de Scripts em Python


   Neste Post vamos criar uma Mini-Interface para executar nossos testes, a mesma tem que fazer 3 coisas básicas. 

1. A primeira coisa é ler um arquivo .json que vai conter dados sobre os testes, e pegar qual .json vai ser lido pelo mesmo.
2. O segundo passo é executar o teste de forma isolada.
3. O Terceira passo após a execução capturar os logs e matar os Processos.

   No entanto tem um grande problema que pode acontecer nesse processo, não matar os processos filhos daquele determinado processo, assim você deixa acumular processo em memória ou seja acumulando lixo no sistema, deixando sua Interface lenta. Outro problema que já evidenciei é a tentativa de o próprio teste tentar fazer algo atribuído a Interface, isso é uma coisa que não vai funcionar de maneira adequada.
   Abaixo vemos com mais detalhes sobre o determinado problema de muitas Interface não funcionando bem, é porque precisa matar os processos de forma recursiva, neste caso vamos utilizar o Psutil:




children(recursive=False)
Return the children of this process as a list of Process objects, preemptively checking whether PID has been reused. If recursive is True return all the parent descendants. Example assuming A == this process:
A ─┐
   │
   ├─ B (child) ─┐
   │             └─ X (grandchild) ─┐
   │                                └─ Y (great grandchild)
   ├─ C (child)
   └─ D (child)

>>> p.children()
B, C, D
>>> p.children(recursive=True)
B, X, Y, C, D
Note that in the example above if process X disappears process Y won’t be returned either as the reference to process A is lost.

# Funcao do PsUtil pra matar os processos filhos de forma recursiva,
# caso der erro ao matar o processo, no .json tem alguns selecionados.
def kill_recursive(self, proc_pid, json_file):
    print (
"Matando o Processo de Forma Recursiva: " +str(proc_pid))
    try:
        process = Process(proc_pid)
        for proc in process.children(recursive=True):
            proc.kill()
        process.kill()
    except NoSuchProcess:
        print ("o processo nao existe mais.")
        self.list_kill(json_file)


Outro problema que resolvemos no código abaixo é abrir o script em um sub-console, o que pode ocorrer que muitas das vezes a Interface poder atrapalhar na execução dos testes, caso a execução aconteça no mesmo processo da Interface


self.process = Popen([sys.executable, self.command], creationflags
=CREATE_NEW_CONSOLE,stdin=PIPE, stdout=PIPE, stderr=PIPE, )


Com as dicas acima, vamos conseguir resolver muitos problemas na hora da execução dos testes. Vou criar um vídeo explicativo e colocar nosso projeto no bitbucket.org depois. Outra Solução é executar os testes através de uma ferramenta de Integração Continua como Jenkins, no entanto na Interface você pode expandir e fazer coisas mais além, como controlar as máquinas virtuais, armazenar os dados dentro de banco de dados para ter dados estatísticos para analisar futuramente.

Segue o código do Post realizado, como fiz bem rápido, precisa de alguns melhorias: https://bitbucket.org/masters_test/interface
git clone git@bitbucket.org:masters_test/interface.git

Problema:
Como o mundo não é mil maravilhas temos um problema grave, dependendo do projeto, alguns programas após inicializados não tem como matar ele, neste caso use o os.startfile, não use o popen, quando colocar na integração continua ele vai falhar, e você não vai saber porque.

Referências:
[1] http://pythonhosted.org/psutil/
[2] https://pypi.python.org/pypi/psutil
[3] https://docs.python.org/2/library/subprocess.html#subprocess.CREATE_NEW_CONSOLE

[4] https://docs.python.org/3.6/library/os.html



sábado, 21 de maio de 2016

Criando Testes com Psutil matando processos (Automação em Python para Desktop)


    O Psutil (Processos e Utilitários do Sistema) é uma biblioteca multi-plataforma para recuperação de informações sobre a execução de processos e utilização do sistema (CPU, memória, discos, rede) em Python. É útil principalmente para a monitorização do sistema, criação de perfis e limitando recursos e gestão de processos em execução do processo. 

  O mesmo implementa muitas funcionalidades oferecidas pelas ferramentas de linha de comando, tais como: ps, top, lsof, netstat, ifconfig, who, df, kill, free, nice, ionice, iostat, iotop, uptime, pidof, tty, taskset, pmap. Atualmente ele suporta Linux, Windows, OSX, Sun Solaris, FreeBSD, OpenBSD e NetBSD, ambas as arquiteturas de 32 bits e de 64 bits, com versões de Python de 2,6 para 3,5 (usuários do Python 2.4 e 2.5 podem usar 2.1.3 versão). 

  Resumindo é um Canivete Suíço para auxiliar nos testes automatizados. Como assim? Você pode monitorar o consumo de memoria/processamento do seu aplicativo em um determinado teste, ou verifica o antes e o depois de um determinado teste, tendo o total de consumo de memoria no sistema operacional, você pode criar um testes de instalação do seu produto e verificar se o aplicativo após a instalação esta em memoria, assim como desinstalação do seu produto verificando se foram removidos da memoria do sistema operacional. 

  Em sistema embarcado já fiz inúmeros testes tendo que pegar a memoria de um determinado teste, por um período de tempo, por exemplo em um teste o Middleware estava travando em uma funcionalidade quando você voltava do Standby. Com o Psutil podemos monitorar esse teste de forma melhor. O Middleware era em linux eu usava o top e o free, em sistemas desktop o Psutil é maravilhoso, podemos verificar monitorar o uso de memoria, processamento, rede e disco.

Vamos aos exemplos práticos, abaixo funções para pegar o pid de um processo passando o nome, matar uma lista de processos via Psutil e via console e também de forma remota, é super prático e rápido. 
 import subprocess  
 import psutil  
 class TaskKill:  
   def __init__(self):  
     pass  
   # funcao que me passa o nome do app e me retorna o pid.  
   def list_pid(self, app):  
     pid = ''  
     if app:  
       for proc in psutil.process_iter():  
         try:  
           pinfo = proc.as_dict(attrs=['pid', 'name'])  
           if pinfo['name'] == app:  
             pid = pinfo['pid']  
         except psutil.NoSuchProcess:  
           print "o processo nao existe mais."  
           return pid  
         else:  
           print(pinfo)  
     else:  
       print "Voce precisa enviar o nome do processo!"  
     return pid  
   # funcao que me passa uma lista de processo por nome e me retorna uma lista de processos.  
   def lista_processos(self, app):  
     proc_kill = []  
     for proc in psutil.process_iter():  
       try:  
         pinfo = proc.as_dict(attrs=['pid', 'name'])  
         if pinfo['name'] == app:  
           proc_kill.append(proc)  
       except psutil.NoSuchProcess:  
         print "O processo nao existe mais."  
         pass  
       else:  
         print(pinfo)  
     return proc_kill  
   # Funcao que forca matar o processo via force no console.  
   def kill_force(self, pid):  
     if pid:  
       p = psutil.Process(pid)  
       app = p.name()  
       for proc in psutil.process_iter():  
         try:  
           pinfo = proc.as_dict(attrs=['pid', 'name'])  
           if pinfo['name'] == app:  
             print "notepad found!"  
             subprocess.check_output('taskkill /PID ' + str(pid) + ' /F', shell=True)  
             return True  
         except Exception, e:  
           print "Erro Desconhecido: ", e  
           pass  
       else:  
         print "Pid nao enviado!"  
     return False  
   def on_terminate(self, proc):  
     print("process {} terminated with exit code {}".format(proc, proc.returncode))  
   # funcao de envia uma lista de processos e mata o processo via psutil.  
   def psutil_kill(self, procs_kill):  
     status = False  
     procs = procs_kill # a list of Process instances  
     for p in procs:  
       try:  
         p.terminate()  
         print "Terminate processo!"  
         status = True  
       except psutil.NoSuchProcess:  
         print "O processo nao existe mais."  
         pass  
     gone, alive = psutil.wait_procs(procs, timeout=10, callback=on_terminate)  
     for p in alive:  
       print ("couldn't terminate process %s" % p)  
       try:  
         p.kill()  
         print "Kill processo!"  
         status = True  
       except psutil.NoSuchProcess:  
         print "O processo nao existe mais."    
     return status  
   # funcao que matar um processo de forma remota na rede, usando o pskill.  
   def kill_force_remote(self, computer, pid, user, password):  
     print "notepad found!"  
     try:  
       subprocess.check_output(  
         'C:\SysinternalsSuite\pskill.exe -t \\' + '\\' + str(computer) + ' -u ' + str(user) + ' -p ' + \  
         str(password) + ' ' + str(pid), shell=True)  
       return True  
     except Exception, e:  
       print "Erro generico: ", e  
     return False  
 if __name__ == '__main__':  
   obj = TaskKill()  
   pid_num = obj.list_pid('notepad++.exe')  
   test = obj.kill_force(pid_num)  
   print "Kill App: " + str(test)  

Resultado:
C:\Python27\python.exe C:/Users/reiload/Dropbox/python_functions/kill_app.py
{'pid': 0, 'name': 'System Idle Process'}
{'pid': 4, 'name': 'System'}
{'pid': 7120, 'name': 'chrome.exe'}
{'pid': 7444, 'name': 'chrome.exe'}
{'pid': 7548, 'name': 'WUDFHost.exe'}
{'pid': 7964, 'name': 'zatray.exe'}
{'pid': 8064, 'name': 'chrome.exe'}
{'pid': 8088, 'name': 'taskhostex.exe'}
{'pid': 8128, 'name': 'GWX.exe'}
{'pid': 9028, 'name': 'python.exe'}
{'pid': 9124, 'name': 'dasHost.exe'}
{'pid': 9272, 'name': 'chrome.exe'}
{'pid': 9368, 'name': 'chrome.exe'}
{'pid': 9396, 'name': 'chrome.exe'}
{'pid': 9556, 'name': 'cmd.exe'}
{'pid': 9820, 'name': 'chrome.exe'}
{'pid': 10084, 'name': 'jucheck.exe'}
{'pid': 10164, 'name': 'cmd.exe'}
{'pid': 10324, 'name': 'audiodg.exe'}
{'pid': 10836, 'name': 'chrome.exe'}
{'pid': 10848, 'name': 'conhost.exe'}
{'pid': 11832, 'name': 'python.exe'}
{'pid': 12316, 'name': 'fsnotifier.exe'}
{'pid': 12320, 'name': 'pycharm.exe'}
{'pid': 12620, 'name': 'conhost.exe'}
{'pid': 12812, 'name': 'python.exe'}
{'pid': 12864, 'name': 'taskeng.exe'}
{'pid': 12932, 'name': 'chrome.exe'}
{'pid': 13080, 'name': 'chrome.exe'}
{'pid': 13188, 'name': 'conhost.exe'}
{'pid': 13544, 'name': 'conhost.exe'}
{'pid': 14564, 'name': 'chrome.exe'}
{'pid': 15032, 'name': 'notepad++.exe'}
notepad found!
Kill App: True

Process finished with exit code 0

    Quem já não precisou matar um processo no braço? Aqui temos um exemplo de forma automatizada e super prático em Python. Na função  kill_force_remote, se você não sabe qual é o PID, passa o nome do processo que vai funcionar mesmo assim. O que pode ocorrer de o script não funcionar é porque você não tem permissão necessária para o mesmo, podemos adicionar o except psutil.AccessDenied, que vai informar que houve acesso negado. Podemos ir um pouco além com o DDT (data driven test), para fazer ele ler vários processos através de um arquivo de json.
   Se você tem um servidor e todo dia tem que matar uma lista de processos na mão, aqui você tem a solução de seus problemas, fazendo isso de forma automatizada, bom espero que gostem e até o próximo Post.

Referências:
[1] http://pythonhosted.org/psutil/
[2] https://pypi.python.org/pypi/psutil
[3] https://technet.microsoft.com/en-us/sysinternals/pskill.aspx 
[4] https://pypi.python.org/pypi/ddt