5111
Comentário:
|
8165
|
Deleções são marcadas assim. | Adições são marcadas assim. |
Linha 63: | Linha 63: |
"Depurar é duas vezes mais difícil que escrever o código pela primeira vez. Portanto, se você escreve o código da forma mais inteligente possível, você não é, por definição, inteligente o suficiente para depurá-lo." -- Brian W. Kernighan. Todo mundo testa seu software em algum nível, ainda que apenas executando e experimentando (tecnicamente conhecido como "teste de fumaça" ["smoke testing"]). A maioria dos programadores faz uma certa quantidade de testes exploratórios, o qual envolve a execução através de vários caminhos funcionais em seu código e vendo se eles funcionam. Teste sistemático, no entanto, é um assunto diferente. Testes sistemáticos simplesmente não podem ser feitos de forma adequada sem uma certa (grande!) quantidade de automação, pois cada mudança no software significa que o mesmo precisa ser totalmente testado de novo. Abaixo, vou apresentar você a alguns conceitos de teste automatizado de nível mais baixo e mostrar como usar as estruturas embutidas no Python para começar a escrever testes. |
|
Linha 65: | Linha 73: |
Existem vários tipos de testes que são particularmente úteis para programadores de pesquisa. ''Testes unitários'' são testes para unidades de funcionalidade razoavelmente pequenas e específicas. ''Testes funcionais'' testam caminhos funcionais inteiros através do seu código. ''Testes de regressão'' asseguram que (dentro da resolução dos seus registros) a saída do seu programa não mudou. Todos os três tipos de teste são necessários de formas diferentes. Testes de regressão mostram quando ocorrem mudanças inesperadas de comportamento e podem confirmar que o processamento básico dos dados permanece funcionando. Para cientistas, isto é particularmente importante se você está tentando vincular resultados de pesquisas passadas a novos resultados: se você não consegue mais replicar seus resultados originais utilizando o código modificado, então vocês deve suspeitar do código, ''a menos que'' as mudanças sejam intencionais. Em contraste, tanto testes unitários quanto funcionais tendem a ser baseados em ''expectativas''. Quero dizer com isso que você usa os testes para estabelecer qual comportamento você ''espera'' do seu código e escreve seus testes de forma que eles ''assumam'' que tais expectativas sejam atendidas. A diferença entre testes unitários e funcionais é nebulosa na maioria das implementações atuais. Testes unitários tendem a ser mais curtos e requerem menos preparação (setup) e encerramento (teardown), enquanto testes funcionais poderm ser bastante longos. Gosto da distinção de Kumar McMillan: testes funcionais mostram ''quando'' seu código está quebrado, enquanto que testes unitários mostram ''onde'' seu código está quebrado. Ou seja, por causa da granularidade mais fina dos testes unitários, um teste unitário quebrado pode identificar um trecho de código em particular como fonte de um erro, enquanto que os testes funcionais meramente mostram que uma funcionalidade está quebrada. |
(Esse texto é uma tradução de Intermediate and Advanced Software Carpentry in Python, de C Titus Brown. O original, segundo o autor, estão licenciados sob a Creative Commons, então a tradução também está.)
Carpintaria de Software Intermediária e Avançada em Python
Bem-vindo! Você acabou de cair nas apostilas de um curso que eu apresentei no Lawrence Livermore National Lab, entre 12 e 14 de junho de 2007.
Essas notas foram planejadas para acompanhar minha palestra, que era uma demostração de de várias características e pacotes "intermediários" de Python. Como a demonstração era interativa, essas notas não são notas completas do que foi apresentado no curso. (Perdoe-me por isso; eles atualizaram minhas apostilas para serem mais completas...)
Entretanto, todas as 70 páginas são livres para ver e imprimir; então, aproveite.
Todos os erros são, naturalmente, meus. Note que quase todos os exemplos começando com >>> são doctests, então você pode pegar o fonte e rodar doctest sobre ela para garantir que eu fui honesto. Só faça-me um favor e rode os doctests com Python 2.5
Note que o primeiro dia do curso foi até o final de "Testando seu software"; o segundo dia foi até o final de "Recursos online sobre Python"; e o terceiro dia terminou o curso.
Códigos de exemplo (a maior parte das seções sobre sobre extensões em C) estão disponíveis aqui; veja o README para mais informações.
Conteúdo
- Carpintaria de Software Intermediária e Avançada em Python
- Python Idiomático
-
Estruturando, Testando e Mantendo Programas Python
- Programando para reusabilidade
- Módulos e scripts
- Pacotes
- Uma pequena digressão: nomes e formatação
- Outra pequena digressão: doctstrings
- Compartilhando dados entre código
- Escopo: uma digressão
- De volta ao compartilhamento de dados
- Como módulos são carregados (e quando código é executado)
- PYTHONPATH, e encontrando pacotes e módulos duranto o desenvolvimento
- setup.py e distutils: a maneira à antiga de instalar pacotes Python
- setup.py, eggs e easy_install: a nova maneira da moda de instalar pacotes Python
- Testando seu software
-
Uma Introdução Estendida ao Framework de Teste Unitiário nose
- O que são testes unitários?
- Por que usar um framework? (e por que nose?)
- Alguns poucos exemplos simples
- Um guia um tanto mais completo para descoberta de testes e execução
- A linha de comando do nose
- O plugin 'attrib' -- rodando seletivamente subconjuntos de testes
- Rodando nose programaticamente
- Escrevendo plugins -- um guia simples
- Ressavlas ao nose -- avise o comprador, ocasionamente
- Python Idiomático revisitado
- Mensurando e Aumentando Performance
- Acelerando Python
- Ferramentas para Ajudar Você a Trabalhar
- Recursos Online sobre Python
- Embrulhando(?) C/C++ para Python
- Pacotes para Multiprocessamento
- Pacotes úteis
- Python Idiomático 3: new-style classes
- GUI Gossip
- Python 3.0
Python Idiomático
Alguns tipos de dados básicos
List comprehentions
Criando seus próprios tipos
Iterators
Generators
assert
Conclusões
Estruturando, Testando e Mantendo Programas Python
Programando para reusabilidade
Módulos e scripts
Pacotes
Uma pequena digressão: nomes e formatação
Outra pequena digressão: doctstrings
Compartilhando dados entre código
Escopo: uma digressão
De volta ao compartilhamento de dados
Como módulos são carregados (e quando código é executado)
PYTHONPATH, e encontrando pacotes e módulos duranto o desenvolvimento
setup.py e distutils: a maneira à antiga de instalar pacotes Python
setup.py, eggs e easy_install: a nova maneira da moda de instalar pacotes Python
Testando seu software
"Depurar é duas vezes mais difícil que escrever o código pela primeira vez. Portanto, se você escreve o código da forma mais inteligente possível, você não é, por definição, inteligente o suficiente para depurá-lo." -- Brian W. Kernighan.
Todo mundo testa seu software em algum nível, ainda que apenas executando e experimentando (tecnicamente conhecido como "teste de fumaça" ["smoke testing"]). A maioria dos programadores faz uma certa quantidade de testes exploratórios, o qual envolve a execução através de vários caminhos funcionais em seu código e vendo se eles funcionam.
Teste sistemático, no entanto, é um assunto diferente. Testes sistemáticos simplesmente não podem ser feitos de forma adequada sem uma certa (grande!) quantidade de automação, pois cada mudança no software significa que o mesmo precisa ser totalmente testado de novo.
Abaixo, vou apresentar você a alguns conceitos de teste automatizado de nível mais baixo e mostrar como usar as estruturas embutidas no Python para começar a escrever testes.
Uma introdução a conceitos sobre teste
Existem vários tipos de testes que são particularmente úteis para programadores de pesquisa. Testes unitários são testes para unidades de funcionalidade razoavelmente pequenas e específicas. Testes funcionais testam caminhos funcionais inteiros através do seu código. Testes de regressão asseguram que (dentro da resolução dos seus registros) a saída do seu programa não mudou.
Todos os três tipos de teste são necessários de formas diferentes.
Testes de regressão mostram quando ocorrem mudanças inesperadas de comportamento e podem confirmar que o processamento básico dos dados permanece funcionando. Para cientistas, isto é particularmente importante se você está tentando vincular resultados de pesquisas passadas a novos resultados: se você não consegue mais replicar seus resultados originais utilizando o código modificado, então vocês deve suspeitar do código, a menos que as mudanças sejam intencionais.
Em contraste, tanto testes unitários quanto funcionais tendem a ser baseados em expectativas. Quero dizer com isso que você usa os testes para estabelecer qual comportamento você espera do seu código e escreve seus testes de forma que eles assumam que tais expectativas sejam atendidas.
A diferença entre testes unitários e funcionais é nebulosa na maioria das implementações atuais. Testes unitários tendem a ser mais curtos e requerem menos preparação (setup) e encerramento (teardown), enquanto testes funcionais poderm ser bastante longos. Gosto da distinção de Kumar McMillan: testes funcionais mostram quando seu código está quebrado, enquanto que testes unitários mostram onde seu código está quebrado. Ou seja, por causa da granularidade mais fina dos testes unitários, um teste unitário quebrado pode identificar um trecho de código em particular como fonte de um erro, enquanto que os testes funcionais meramente mostram que uma funcionalidade está quebrada.
O módulo doctest
Tests unitários com unittest
Testes com nose
Análise de cobertura de código
Adicionando testes para um projeto existente
Pensamentos finais sobre testes automatizados
Uma Introdução Estendida ao Framework de Teste Unitiário nose
O que são testes unitários?
Por que usar um framework? (e por que nose?)
Alguns poucos exemplos simples
Suporte a testes
Exemplos são incluídos!
Um guia um tanto mais completo para descoberta de testes e execução
Rodando testes
Depurando descoberta de testes
A linha de comando do nose
-w: Especificando o diretório corrente
-s: Não capturar stdout
-v: Saída de informação e debug
Especificando uma lista de testes para rodar
== Rodando doctests no nose ===
O plugin 'attrib' -- rodando seletivamente subconjuntos de testes
Rodando nose programaticamente
Escrevendo plugins -- um guia simples
Ressavlas ao nose -- avise o comprador, ocasionamente
== Créditos==
Python Idiomático revisitado
sets
any e all
Exceções e hierarquia de exceções
Decorators de funções
try/finally
Argumentos de funções e wrapping functions
Mensurando e Aumentando Performance
Que profiler devo usar?
Mensurando snippets de código com timeit
Acelerando Python
psyco
Instalando psyco
Usando psyco
pyrex
Ferramentas para Ajudar Você a Trabalhar
IPython
screen e VNC
Trac
Recursos Online sobre Python
Embrulhando(?) C/C++ para Python
Wrapping manual
Embrulhando código Python com SWIG
Embrulhando código C com pyrex
ctypes
SIP
== Boost.Python==
Recomendações
Uma ou duas outras notas sobre wrapping
Pacotes para Multiprocessamento
threading
== Escrevendo (e indicando) extensões C threadsafe ==
parallelpython
Rpyc
pyMPI
multitask
Pacotes úteis
subprocess
rpy
matplotlib
Python Idiomático 3: new-style classes
Atributos gerenciados
Descriptors
GUI Gossip