Como fazer um carro escrever testes de código para você

Nós vivemos em um mundo imperfeito. As pessoas escrevem código aqui e são naturalmente propensas a cometer erros . Tudo ficaria bem, os erros podem ser detectados na fase de teste e não podem prejudicar ninguém. É possível se você escrever testes. O que as pessoas não gostam de fazer por algum motivo. Mas talvez haja esperança - geração automática de testes a partir de código escrito.

Julia Volkova quer testar a ideia na realidade e está tentando mudar a criação de testes com base no código para uma máquina, sem usar instruções ou contratos adicionais. Julia irá falar sobre as descobertas que a jornada traz ao mundo da metaprogramação, AST, análise e tokenização e o que tudo isso nos permitiu alcançar em testes de geração automática, no Moscow Python Conf ++. Enquanto isso, perguntei de onde surgiu a idéia - para automatizar os testes, qual é a base do protótipo e o que resta fazer.

Julia Volkova (xnuinside) Senior Python Developer GridDynamics. pet-, . , legacy-, , . , «» . -, .

— , , , ? , . ?

Eu acho que existem várias razões. Primeiro, a maioria de nós é preguiçosa por natureza. Poucas pessoas gostam diretamente de fazer testes - acordam de manhã e dizem: "Precisamos começar o dia com 15 testes, caso contrário tudo ficará ruim, mas ao mesmo tempo minha vida não terá sucesso". A preguiça natural se manifesta com mais frequência, especialmente quando você vê que o método não é muito interessante, possui um código claro e primitivo, mas você ainda precisa cobri-lo com testes.
Poucos escrevem TDD, então você não apenas precisa escrever um teste, mas também dedicar algum tempo ao código.
O problema é que uma quantidade infinita de tempo não é alocada para desenvolvimento. Sempre há produtos de lista de desejos com tempo limitado. Nas equipes de produto, em geral, tudo era necessário ontem, porque tempo é dinheiro. Parece aos gerentes que, quanto mais esverdearmos um recurso, mais caro e melhor será o nosso produto. E nem sempre é óbvio que testar a cobertura, a qualidade do código afeta diretamente a velocidade subsequente de adicionar recursos, suporte a códigos, atualização etc.

Costumamos culpar os gerentes por tudo e dizemos que eles não nos dão tempo suficiente; caso contrário, sentaríamos e escreveríamos testes. De fato, esse nem sempre é o caso. E nem sempre os desenvolvedores robustos experientes dizem para escrever testes, e os colegas mais jovens não querem.

Estou na área de TI há muito tempo, mas estou envolvido diretamente no desenvolvimento por 3 a 4 anos. Antes disso, trabalhei mais em posições gerenciais e vi diferentes desenvolvedores. Há muitas pessoas que não podem ser chamadas de inexperientes, porque escrevem código há 10 anos, mas ao mesmo tempo acreditam que testes como tais não são necessários. Suponha que você não precise cobrir o código com testes de unidade, porque existe um engenheiro de controle de qualidade que precisa detectar bugs. E eles não acham que esse engenheiro pode cobrir nem todos os casos com testes de ponta a ponta.

"Se você não chega a tais extremos, o que acha, quem deve escrever os testes?" Deveria ser o próprio programador, o júnior ou, inversamente, o desenvolvedor mais legal da equipe?

- Se estamos falando de testes de unidade, definitivamente não deve ser o controle de qualidade. Definitivamente, esses devem ser os testes verificados, aprovados e escritos antes de serem confirmados e devem ser direcionados para receber solicitações, em nenhum caso outra pessoa deve escrevê-los mais tarde. Por exemplo, eu, como um desenvolvedor preguiçoso não júnior, apenas colocava os juniores para escrever testes de código primitivo. Há coisas para as quais basta ler o código em um nível intermediário e escrever afirmações, esse trabalho é bastante adequado para juniores e será útil para seu desenvolvimento.

Estes são testes de unidade que simplesmente abrangem o código de estado. Esses testes não verificam a validade da função em relação ao requisito de tarefa na tarefa, mas apenas certifique-se de que o código faça o que faz e o faça corretamente ...

Mas para verificar a validade do código para requisitos de negócios, para a lógica de negócios, no entanto, uma pessoa que implementa esses requisitos deve. Ele deve entender o que e como ele cobre os testes. Mas não está claro como isso ajudará se uma pessoa não entendeu o problema inicialmente, escreveu um método que o resolve incorretamente, mas fez o teste correto para esse método incorreto.

- Podemos dizer que o problema é que as pessoas têm uma péssima idéia de como está o processo de desenvolvimento de software?

Isso é muito subjetivo. Você se imagina como uma unidade de desenvolvedores que entende que os testes são necessários, por que são necessários e acha que isso é verdadeiro e bom. Mas há uma camada bastante grande de desenvolvedores que acreditam que isso é redundante. E, de certa forma, os gerentes provavelmente estão certos do seu jeito quando dizem que os testes não precisam cobrir todo o código, apenas testes manuais no estágio são suficientes.
Nem sempre é correto dizer que uma pessoa que não gosta de testes é um desenvolvedor não qualificado.
Ele tem uma visão própria, e não para eu julgar. Ainda encontro frequentemente desenvolvedores que escrevem código há 10 anos e digo que é redundante cobrir tudo com testes de unidade, testes de fumaça suficientes e trabalho de controle de qualidade.

Por sua vez, sinto-me desconfortável em um projeto no qual não há testes de unidade para funções. É importante para mim que haja pelo menos testes que garantam proteção contra o fator humano, capaz de capturar uma vírgula colocada aleatoriamente ou um nome de chave alterado em um ditado. Mas não gosto de gastar tempo nisso, porque sempre quero fazer mais tarefas "inteligentes". Portanto, estou pensando em ferramentas para automatizar o processo de escrever testes.

- Você acha que o Python é digitado dinamicamente e não verifica nada no estágio de compilação? Poderia ser mais fácil em outros idiomas com isso?

- Eu acho, joga e forte. Esta é uma história eterna sobre tipos, mas com o advento das anotações de tipos, ficou mais fácil trabalhar com elas.

Por exemplo, no Python, pode haver cadeias de funções aninhadas, onde o esperado no final da lista, por algum motivo, se transforma em um dicionário. A execução pode nunca alcançar a função final, mas, em alguns casos, se for o caso, ocorre um erro excepcional.

Obviamente, com uma linguagem digitada, isso não pode acontecer em princípio, porque um erro já ocorrerá no estágio de compilação. A esse respeito, é claro, o Python fornece maneiras adicionais de se dar um tiro no pé (na cabeça e em outros lugares). Especialmente se você trabalha com grandes projetos com lógica ramificada, onde os dados podem ser despejados em diferentes variações, em diferentes agregações.

- O que fazer então com a tipificação? Você acha que a digitação deve estar no máximo ou no mínimo? Qual deve ser o equilíbrio da digitação do código dinâmico?

- Isso é novamente bastante subjetivo. Muitas pessoas acessaram o Python precisamente porque não há digitação e porque tudo é muito flexível e conveniente. Você não deve esquecer isso e não eliminar uma enorme camada de desenvolvedores, incluindo cientistas e analistas de dados que também escrevem código. Suponha que eu, como desenvolvedor de back-end, fique naturalmente mais confortável quando a digitação estiver em todo lugar. Idealmente, mypy também funciona.

Mas na maioria dos projetos em que participei, isso não é possível. Como o projeto também possui analistas de dados que dizem isso porque escrevem em Python porque não querem mexer com tipos, é muito conveniente para eles.
Um grande número de pessoas acredita nisso, além de Python, na ausência de tipos e digitação.
Você precisa crescer até um certo nível para entender quando e por que isso se torna um sinal de menos. Em alguns pequenos scripts Python ou em pequenos projetos, também não uso tipos, porque sei que em um script de duas funções, os tipos não são particularmente necessários. Mas isso é algo que, grosso modo, eu rapidamente ajoelhei para puxar algo para fora da base. E em projetos maiores, tento adicionar tipos ao máximo em todos os lugares, se não houver resistência de outros desenvolvedores.

- Eu concordo completamente com você nisso. Resta apenas entender como usar tipos, porque esse é um tópico obscuro separado.

: «, Haskell , : , . Python , , ».

— . , , legacy- smoke-. . ?

- Não vou dizer que minha abordagem é melhor, é apenas diferente. Cobrir seu código com testes de fumaça é bom quando você pode. Meu projeto anterior foi a dor por excelência associada aos testes. Era uma plataforma de ciência de dados de 8 microsserviços e 20 mil linhas de código. O problema é que a plataforma recebe uma grande quantidade de dados e características de veículos, estações e cidades, vários estacionamentos e tipos de suprimentos, agrega e cria um enorme conjunto de possíveis programações para esses veículos em todo o mundo. O cronograma leva em conta um grande número de condições da categoria em que você pode reabastecer o veículo, onde fazer uma parada intermediária.

Existem muitos métodos diferentes no sistema que podem ser usados ​​em 1-2 situações, das quais talvez nenhum dos clientes se lembre. Na verdade, escrever testes de fumaça se transforma em testes de escrita para todo o sistema, levando em consideração todas as funções e suas combinações.

O teste de fumaça deve verificar se tudo funciona na saída e não quebra minimamente. Um teste de fumaça muito primitivo iniciado pelo sistema e de alguma forma funciona não traz nenhum benefício no nosso caso. Digamos que verificamos se há uma conexão com o banco de dados, algo está iniciando, a interface do usuário está recebendo algum tipo de API. E então um passo para a esquerda, um passo para a direita - e nada funciona. Ou seja, há um teste de fumaça, por assim dizer, mas os erros ainda voam da produção.

Nesse sistema, os testes de unidade funcionaram perfeitamente: quando é claramente monitorado que as funções não foram alteradas, elas não foram quebradas após algumas alterações no código. O código também é diferente. Projetos diferentes, tarefas diferentes precisam de abordagens diferentes para o teste.

A ideia em que estou trabalhando atualmente só pode ser chamada de geração automática de testes condicionalmente. É sim uma ferramenta de desenvolvedor. Quero obter uma ferramenta que escreva testes para mim e execute todo o código que pode ser executado sem mim.

Vou dar um exemplo. Há uma pequena função que pega um dicionário, dele algum valor e uma chave. Essa chave é muito importante para os negócios, mas, do ponto de vista do código, é uma operação bastante primitiva: retire do dicionário, mesmo que seja uma chave aninhada várias vezes; verifique se ele está lá, se ele não é zero; troque-o ou talvez apenas retorne o valor. Este é um código bastante primitivo, exatamente do ponto de vista do AST. Eu não quero perder meu tempo com ele e escrever testes. Eu quero que o carro faça isso por mim.

Este é precisamente um metaprograma com um código de entrada e um código de saída. Digamos, para o módulo py, que diz: "Aqui eu afirmo, eu o" assisti "que há erros de aumento nessa condição, valores válidos retornados em tal situação, algo mais aconteceu com esse argumento" . Na verdade, ele faz o trabalho em que eu próprio olhava o que é alimentado na entrada da função e a escrevia no teste.

Quero que o programa gere o mínimo que ele próprio possa executar para mim. Mas esse deve ser um arquivo de teste, no qual, se desejado, você pode alterar ou expandir algo. Que você pode confirmar no Git, teste de teste etc.

- Quanto você pode confiar nesses testes gerados automaticamente? O que quero dizer - quanto eles estão vinculados a uma implementação específica e como eles se comportam sob mudanças normais na lógica de negócios ou na refatoração?

- A idéia é pegar o código na forma em que está agora e com base nele para gerar testes válidos no momento.

Obviamente, você pode gerar novamente os testes sempre, mas isso não estará correto, pois não haverá rastreamento do estado da alteração do código. Dessa forma, ainda há diferenças de teste para isso, ou seja, os testes são gerados apenas para o que não foi coberto pelos testes anteriormente. E os testes já criados precisam ser suportados por você.

Talvez isso seja um pouco de paranóia, mas até agora duvido que, com a geração automática, seja possível garantir que, regenerando os testes, você não cubra o código válido com testes válidos. Uma coisa é que, em fevereiro de 2019, eu gerei testes e, se você alterar a lógica, você também altera os testes, porque sabe quais alterações foram feitas. Você sabe por que os testes foram reprovados e pode corrigi-los de acordo. E é uma questão completamente diferente quando você os regenera sempre. Os testes serão válidos, mas apenas para esse estado alterado do código.
Quero obter uma ferramenta para o desenvolvedor, e não uma peça para aumentar a cobertura do código.

- Quais podem ser métricas de sucesso? Como entender que geramos testes bem?

Vou citar o que presto atenção, sem o qual me parece que os testes não fazem sentido. É imperativo que todos os casos de comportamento do código descritos pelo desenvolvedor sejam processados ​​nos testes. Por exemplo, se houver um se isso não retornar nada, mas gravar um log, no teste esse log deverá funcionar. Não apenas as pessoas escrevem avisos e imprimem. Portanto, se em algum lugar houver um processamento de erro de aumento, você precisará resolvê-lo em um teste. Se repentinamente raise desaparecer, ou seja, haverá uma mudança na lógica do código, isso também precisará ser resolvido.

Da mesma forma, se houver instruções if, deve haver processamento na declaração de cada condição. Então o teste estará mais ou menos próximo da verdade. E não esqueça que tudo deve ser iniciado, e não apenas emitir "sucesso" no PyTest com corpos de teste vazios.

- Diga-me o quão difícil é tecnicamente fazer. Parece uma tarefa bastante difícil.

Sim, essa é uma tarefa muito difícil, e provavelmente é esse fato e várias outras circunstâncias que me levaram a falar sobre isso em um relatório sobre o Moscow Python Conf ++. Quero abordar este tópico, interessar outras pessoas e discutir soluções com eles.

Tenho a sensação de que ninguém apenas tentou fazer isso, porque a tarefa é difícil. Caso contrário, haveria alguns artefatos na rede, como código, descrições, artigos ou pelo menos menciona que existia, mas foi abandonado.

Para entender como isso é difícil, vamos relembrar como o intérprete funciona. Existem operações, instruções no código, o intérprete as executa - boas, não boas, falharam, não falharam - e produz o resultado. Além disso, o desenvolvedor adiciona manualmente novos argumentos, inicia o intérprete novamente, garante que tudo tenha sucesso agora. Mas quando você tenta gerar testes para o código, primeiro você precisa percorrer a árvore AST e entender quais etapas você precisa executar para obter o resultado.

Uma função pode ter muitos grupos de argumentos, estratégias para argumentos e muitos resultados para essas estratégias. Falando em estratégias, quero dizer que, digamos, existem if arg_1==1: raise error. Isso significa que existem alguns grupos arg_1=1para os quais a função sempre retorna um erro. Mas com o argumento, o arg_1>2resultado da função será diferente e um segundo grupo será criado, a segunda estratégia.

Portanto, precisamos encontrar e destacar todos esses grupos de argumentos (se é claro que estão), nos quais a função altera seu comportamento. E então siga a cadeia de ações: o que acontecerá dentro da função com esses argumentos para obter o resultado final.

Além disso, não esquecemos que, além do fato de haver algum argumento, também existem ações dentro da função, por exemplo, atribuir variáveis, chamando outras funções. Ou seja, também obtemos um gráfico das dependências dos métodos nos métodos, quando, para verificar algum código, você deve primeiro obter o resultado de outro código.

Assim, para gerar testes, você deve primeiro obter todas as informações necessárias da árvore AST e, em seguida, gerar argumentos, parâmetros e dados para cada estratégia. Com eles, percorra toda a cadeia de ações, obtenha o resultado e só então teremos um teste válido com diferentes afirmações. Esta é uma tarefa difícil.

Eu não acho que algum dia será possível cobrir 100% de todos os tipos de casos automaticamente, por exemplo, para as enormes telas dos códigos-fonte do Django. É trabalhoso, mas interessante. Até agora, estou curioso para saber onde tenho paciência e força para alcançar.

- Existem exemplos de outros idiomas e áreas em que algo assim funciona?

- Não existem conhecidos semelhantes. Eu acho que porque é mais fácil escrever um teste do que cortar uma ferramenta especial.
Mas tenho a sensação de que mais cedo ou mais tarde automatizaremos o que já estamos fazendo bem.
Há um grande conjunto de desenvolvedores que escrevem bem os testes de unidade. Temos competências suficientes no desenvolvimento de Python para querer escrever uma ferramenta ou biblioteca que faça isso por nós. E escreveremos coisas mais complexas, testes mais complexos.

Há algum tipo de geração de teste em Java, C e .Net. Mas lá também tudo é mais baseado em propriedades ou contratos. Em C, há uma geração de teste caractere por símbolo, parece que apenas olha o código e, com base nisso, faz alguns testes. Mas este é um nível de abstração tão diferente na própria linguagem que não tenho certeza se é uma história semelhante.

Se houvesse algo muito semelhante, é claro que alguém poderia adotar algo, espiar.

- Você acha que estruturas ou talvez técnicas para escrever código Python simplificam ou complicam a tarefa de gerar testes a partir da árvore AST?

- É difícil dizer se, nesse sentido, é muito diferente simplesmente importar alguma biblioteca ou usar uma estrutura diretamente específica. Absolutamente, isso pode complicar bastante o trabalho de algo que altera o comportamento da interpretação de um processo de código, por exemplo, uma extensão C. Como lidar com isso, ainda não sei, mas o uso dos meus terceiros pacotes favoritos até agora neste problema está na necessidade de resolver as importações. Tudo é simples com pacotes integrados, mas com importações tudo se torna mais complicado. Mypy tem algumas idéias e implementações, mas ainda não toco o histórico de importação de pacotes de terceiros.

- Talvez seja algum tipo de técnica - muita dinâmica, o uso de getattr - algo assim? Ou está funcionando bem?

"Funciona perfeitamente bem." Porque getattr ou manipulações com metaclasses são visíveis no AST. Sim, eles precisam ser resolvidos, e isso adiciona alguma complexidade. Mas isso é rastreado de qualquer maneira.

- Já dissemos que os testes gerados automaticamente se destinam principalmente a pessoas. Quão legíveis serão para as pessoas? Haverá muita lógica dentro de cada teste, afirma? Como será a separação entre código e dados, como você a vê?

- Agora, tento adicionar inicialmente todos os tipos de coisas banais aos testes. Suponha que, se houver algum tipo de erro de aumento, não seja apenas com aumento, mas pelo menos deixe um comentário, que tipo de erro, por que aparece, para que a pessoa, depois de ler o teste, entenda o que realmente aconteceu, que argumento leva a qual erro .

Afirma até agora combinadas em um método. Ou seja, se existe uma função e há 5 estados que queremos verificar, até que 5 afirmações entrem na função.

Havia uma idéia para introduzir convenções de nomes, por exemplo: coloque erros no final do erro, os logs de teste também têm algo próprio. Mas adiei por enquanto, porque a questão de como criar o tipo final de testes no código, diretamente um bloco de texto com testes, é a operação de menor custo. Se de repente surgir a ideia de que tudo precisa ser reformatado, será fácil fazer isso - existem afirmações montadas prontas, basta escolher uma aparência diferente para os testes.

- Você suporta unittest ou pytest?

- Pytest. E só porque não quero gastar muita energia na produção agora. O Pytest é bom porque existem muitos plugins, decoradores e vários modificadores fáceis de usar.

A beleza pode ser importante para o usuário final e o desenvolvedor. Mas isso não afeta o desenvolvimento da idéia. Se você precisar dar suporte ao unittest, isso pode ser facilmente adicionado.

- Quanto essa abordagem está relacionada aos testes baseados em propriedades?

- Agora, para gerar argumentos, apenas o tipo moki é usado: você precisa de int, dê int aleatório. Mas essas estratégias serão fáceis de reescrever, por exemplo, comece a usar hipóteses. Embora eu não dedique muito tempo e esforço nisso, porque entendo que posso usar geradores de terceiros como valor. Agora, parece-me, isso não é tão importante quanto trabalhar com a AST.

- Você planeja apoiar a programação de contratos ou de alguma forma se separar de uma maneira especial? Porque ajuda muito no trabalho com testes de unidade, testes baseados em propriedades e testes, em princípio, para entender a lógica de negócios.

- Se por programação de contrato queremos dizer contratos no código, então eu me afasto disso o máximo possível. Porque, quando você pode usar a programação de contratos, basicamente pode codificar os contratos com contratos e gerar testes de unidade com base. E então minha ferramenta não é tão necessária.

Agora tento não pensar em nada que modifique o código. Porque, por exemplo, em projetos de terceirização, nos quais eu enfrentava o problema da falta de testes - e esses eram quase todos os projetos, infelizmente, na empresa atual - era quase impossível tocar no código. Ou seja, era impossível fazer alterações até que você pudesse garantir que esse decorador ou contrato não alterasse todo o componente funcional do código.
Se for possível editar o código, os testes de contrato são bons.
Mas, por enquanto, procedo do fato de que não existe essa possibilidade. E, portanto, com base em contratos, você pode gerar testes de unidade e, de fato, implementar a duplicação de funcionalidades.

- Conte-nos sobre o próximo ponto importante: como testar os testes recebidos e quanto você pode garantir que esses testes realmente testem alguma coisa?

- O teste mutacional não foi cancelado e, em uma imagem ideal do mundo, ele certamente precisa ser usado nesta história. A ideia como um todo é a mesma que se o teste fosse escrito pelo desenvolvedor manualmente. Ou seja, tudo o que está disponível para testes de teste pode ser totalmente aplicado.

- Vamos discutir um pouco a conferência Moscow Python Conf ++. Vamos realizarum dos desenvolvedores de hipóteses que mencionamos várias vezes. O que você estaria interessado em perguntar a ele?

- Eu gostaria de perguntar a Zach sobre onde eles querem desenvolver o projeto junto com os mantenedores: o que adicionar, qual o caminho a ser desenvolvido. Tenho certeza de que Zach agora tem um PR para geração de testes. Eles fazem isso regularmente. Mais precisamente, os decoradores são adicionados aos testes de unidade existentes.

Eu gostaria de discutir as idéias da geração automática de testes em termos de como a hipótese é vista, como os contribuidores o veem. Certamente as pessoas envolvidas em testes nesse nível têm algumas idéias ou talvez alguém já tenha tentado alguma coisa.

“Contamos com isso quando estamos preparando o programa da conferência: para os relatórios definirem tópicos para discussão, durante os quais todos encontrariam novas idéias e orientações para o desenvolvimento. Para quais relatórios você irá?

- Gostaria de ficar chateado e ir a todos os relatórios às 12 horas. Neste momento, haverá Zac Hatfield-Dodds, Andrey Svetlov com um relatório sobre programação assíncrona e Vladimir Protasov com automação de refatoração . Vou para um dos dois últimos e depois vou para Zach no final do relatório ( nota do editor: faça um truque vitalício - ouça quase completamente o novo tópico e chegue ao final do relatório e faça perguntas ao orador com quem você deseja conversar ) .

Deve haver muito interessanterelatório sobre validação de dados , estou interessado diretamente nele. E há mais dois relatórios para os quais eu também iria, mas todos serão paralelos aos meus: este é um relatório de Vitaly Bragilevsky sobre digitação e Christian Heimes sobre criação de perfis . Infelizmente, não consigo encontrá-los de nenhuma maneira.

- Conte-me um pouco mais sobre o tema do seu relatório, por que você está fazendo, o que está fazendo, por que está falando e o que está esperando do discurso?

- Quero mais ferramentas para automatizar processos de desenvolvimento e mais colaborações relacionadas a isso. Existe essa atividade, mas no contexto de escrever constantemente o mesmo código, parece-me que deveria haver mais.

Como eu disse, não há experiência aberta em testes de geração automática em Python. Não está claro se alguém estava fazendo isso; se sim, por que não decolou, não foi. Não sei o quanto a geração de testes baseados em AST será relevante para a comunidade, até onde ela pode ir. Agora estou fazendo isso porque estou interessado no processo em si, estou interessado em explorar as árvores AST, aprender mais sobre como o código Python funciona e encontrar muitas nuances diferentes que não são óbvias ao trabalhar com o código de nível superior. Trabalhar com árvores AST traz muitas descobertas repentinas.

Quero que as pessoas tenham ideias após o relatório, por exemplo, como automatizar algo que elas usam em seu trabalho. Para que alguns deles parem de escrever trechos de código que já escrevem todos os dias e comecem a gerar ou reduzir a quantidade de tempo que leva para escrevê-los. Espero que alguém saia com um novo entendimento de como resolver esse problema.

- Onde você dedica tempo para falar em conferências, escrever suas próprias bibliotecas? Essa pergunta realmente aparece constantemente, muitas pessoas reclamam que não têm tempo para nada.

- Em primeiro lugar, sobre o tempo. Não sou um funcionário muito conveniente para muitas empresas no sentido de não fazer coisas que me parecem ineficazes. Eu tento fazer coisas que são realmente interessantes para mim ou que eu posso fazer de maneira eficaz e correta. Se, por exemplo, um gerente quer que eu corrija algum tipo de bug no momento, o que na verdade não é um bug, mas uma lista de desejos de um cliente novo, não vou me sentar e consertar tudo, porque sei que o cliente voltará e dirá por que você fez isso.
Tento não fazer trabalho desnecessário no trabalho, não fazer o que implicará a perda do meu tempo depois.
Suponha que, se eles me pedirem para implantar na sexta-feira, eu digo: “Gente, eu amo muito todos vocês, todos vocês são ótimos companheiros, mas se você precisar implantar algo agora, implante-se e eu irei para casa. Posso implantá-lo na segunda-feira, podemos falar sobre por que essa situação ocorreu e que você deseja implantar agora na sexta-feira. ” Pode ser doloroso, pela primeira vez, dizer isso ao cliente ou aos gerentes, mas mais tarde as pessoas se acostumam, estudam e não pedem que você faça algo muito urgente na sexta à noite. Eles entendem que, em primeiro lugar, ninguém morreu na sexta-feira passada, quando ninguém foi inundado e nem mesmo ninguém perdeu dinheiro. Tento não fazer algo que me prejudique.

A mesma história sobre bugs - se há muitos bugs que precisam ser corrigidos constantemente, a questão é: por que esses bugs aparecem. Não devemos corrigi-los, mas pense por que existem tantos deles, de onde eles vêm e lute principalmente com o problema raiz. Esses também são problemas sempre dolorosos, quando um gerente ou cliente diz que é urgente corrigir um recurso na produção. Mas você precisa dizer que, se eu tocar neste código agora, talvez você tenha algo diferente desse recurso, não terá produção, já que o código não é coberto por testes, você não pode adicionar outro, porque não nos lembramos do que os outros seis fazem.

Às vezes você precisa se superar e começar a falar. Isso nem sempre é possível, é necessário aumentar para um certo nível de consciência de que, por quanto tempo você gasta em que tipo de trabalho, você é responsável.

Portanto, eu provavelmente tenho tempo. Como tento otimizar meu tempo de trabalho, levo um certo número de horas para concluir uma tarefa. Ao mesmo tempo, entendo que, em uma boa estrutura, deve haver de 1 a 2 horas para dívidas técnicas e algumas melhorias.

Não direi que trabalho 8 horas sem me levantar. Eu olhava para um desenvolvedor que senta e escreve código por 8 horas de tempo de trabalho. Se você tirar meu dia de trabalho habitual, duas horas são apenas todos os tipos de testes, revisão de código, dívida técnica, "buzz" no código. Horas 3 é uma solução para os problemas atuais, uma hora para se comunicar com os gerentes. E as 2 horas restantes estão espalhadas por algum motivo, para discussão com equipes e coisas freelancers.

Há coisas que você está interessado em fazer - você faz e, quando não tem força, elas lhe dão força. Eu tenho muitas atividades diferentes - isso provavelmente é chamado de procrastinação útil - quando faço o que me interessa no momento e não o que preciso fazer. Se você aprender a variar entre o que é interessante e o que ainda é necessário, será o mais bem-sucedido. Você simplesmente não perde tempo se perdendo para fazer o que não quer.

Não há segredo, você só precisa fazer o que gosta, mas ao mesmo tempo sem prejudicar as pessoas ao seu redor e o projeto.

Para obter detalhes sobre como implementar a geração de teste a partir do código Python, além de resolver muitas outras tarefas de um desenvolvedor Python, visite o Moscow Python Conf ++ , que adiamos para 15 de setembro.

All Articles