Criando uma Mini-Interface para Execução de Scripts em Python
Autor: Reinaldo Mateus Rossetti Junior | Publicado: 2016-08-21T09:59:00-07:00




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



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.



&nbsp; &nbsp;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.
&nbsp; &nbsp;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&nbsp;Process&nbsp;objects, preemptively checking whether PID has been reused. If recursive is&nbsp;True&nbsp;return all the parent descendants. Example assuming&nbsp;A == this process:


A ─┐
   │
   ├─ B (child) ─┐
   │             └─ X (grandchild) ─┐
   │                                └─ Y (great grandchild)
   ├─ C (child)
   └─ D (child)

&gt;&gt;&gt; p.children()
B, C, D
&gt;&gt;&gt; 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.&nbsp;


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]&nbsp;https://docs.python.org/2/library/subprocess.html#subprocess.CREATE_NEW_CONSOLE
[4]&nbsp;https://docs.python.org/3.6/library/os.html