Guga-Santos / Job_Insights

Repositório de Análise de Dados da cadeira Ciências da Computação da Trybe

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Boas-vindas ao repositório do Job Insights!

Para realizar o projeto, atente-se a cada passo descrito a seguir, e se tiver qualquer dúvida, nos envie por Slack! #vqv 🚀

Aqui você vai encontrar os detalhes de como estruturar o desenvolvimento do seu projeto a partir deste repositório, utilizando uma branch específica e um Pull Request para colocar seus códigos.

Neste projeto você implementará análises a partir de um conjunto de dados sobre empregos. Suas implementações serão incorporadas a um aplicativo Web desenvolvido com Flask (um framework web muito popular na comunidade Python). Você também terá a oportunidade de escrever testes para a implementação de uma análise de dados. Por fim, como bônus, você terá o desafio de escrever uma rota e view para um recurso novo usando Flask!

Os dados foram extraídos do site Glassdoor e obtidos através do Kaggle, uma plataforma disponiblizando conjuntos de dados para cientistas de dados.

🚵 Habilidades a serem trabalhadas:

  • Utilizar o terminal interativo do Python.
  • Utilizar estruturas condicionais e de repetição.
  • Utilizar funções built-in do Python.
  • Utilizar tratamento de exceções.
  • Realizar a manipulação de arquivos.
  • Escrever funções.
  • Escrever testes com Pytest.
  • Escrever seus próprios módulos e importá-los em outros códigos.
🎛 Linter

Para garantir a qualidade do código, vamos utilizar neste projeto o linter Flake8. Assim o código estará alinhado com as boas práticas de desenvolvimento, sendo mais legível e de fácil manutenção! Para rodá-lo localmente no projeto, execute o comandos abaixo:

python3 -m flake8

⚠️ PULL REQUESTS COM ISSUES DE LINTER NÃO SERÃO AVALIADAS. ATENTE-SE PARA RESOLVÊ-LAS ANTES DE FINALIZAR O DESENVOLVIMENTO! ⚠️

🏕️ Ambiente Virtual
O Python oferece um recurso chamado de ambiente virtual, onde permite sua máquina rodar sem conflitos, diferentes tipos de projetos com diferentes versões de bibliotecas.
  1. criar o ambiente virtual
$ python3 -m venv .venv
  1. ativar o ambiente virtual
$ source .venv/bin/activate
  1. instalar as dependências no ambiente virtual
$ python3 -m pip install -r dev-requirements.txt

Com o seu ambiente virtual ativo, as dependências serão instaladas neste ambiente. Quando precisar desativar o ambiente virtual, execute o comando "deactivate". Lembre-se de ativar novamente quando voltar a trabalhar no projeto.

O arquivo dev-requirements.txt contém todas as dependências que serão utilizadas no projeto, ele está agindo como se fosse um package.json de um projeto Node.js.

🛠 Testes

Para executar os testes certifique-se de que você está com o ambiente virtual ativado.

Executar os testes

$ python3 -m pytest

O arquivo pyproject.toml já configura corretamente o pytest. Entretanto, caso você tenha problemas com isso e queira explicitamente uma saída completa, o comando é:

python3 -m pytest -s -vv

Caso precise executar apenas um arquivo de testes basta executar o comando:

python3 -m pytest tests/nomedoarquivo.py

Caso precise executar apenas uma função de testes basta executar o comando:

python3 -m pytest -k nome_da_func_de_tests

Se desejar que os testes parem de ser executados quando acontecer o primeiro erro, use o parâmetro -x

python3 -m pytest -x tests/test_jobs.py

Para executar um teste específico de um arquivo, basta executar o comando:

python3 -m pytest tests/nomedoarquivo.py::test_nome_do_teste

Se quiser saber mais sobre a instalação de dependências com pip, veja esse artigo.

Logo Flask

Além dos testes com o Pytest, você pode (e vai ser bem bacana) rodar a aplicação flask para visualizar no navegador o resultado do desenvolvimento das funções. Para isso, digite o comando flask run, e acesse o site gerado pelo Flask em http://localhost:5000. No começo do desenvolvimento, você verá que muitas coisas não funcionam, mas conforme você for implementando os requisitos, perceberá que a aplicação web começa a utilizar suas implementações e passa a ganhar vida.

Tela Aplicação

🤝 Depois de terminar o desenvolvimento (opcional)

Para sinalizar que o seu projeto está pronto para o "Code Review", faça o seguinte:

  • Vá até a página DO SEU Pull Request, adicione a label de "code-review" e marque seus colegas:

    • No menu à direita, clique no link "Labels" e escolha a label code-review;

    • No menu à direita, clique no link "Assignees" e escolha o seu usuário;

    • No menu à direita, clique no link "Reviewers" e digite students, selecione o time tryber/students-sd-019-b.

Caso tenha alguma dúvida, aqui tem um video explicativo.

🕵🏿 Revisando um pull request

Use o conteúdo sobre Code Review para te ajudar a revisar os Pull Requests.

🗣 Nos dê feedbacks sobre o projeto!

Ao finalizar e submeter o projeto, não se esqueça de avaliar sua experiência preenchendo o formulário. Leva menos de 3 minutos!

FORMULÁRIO DE AVALIAÇÃO DE PROJETO

🗂 Compartilhe seu portfólio!

Agora que você finalizou os requisitos, chegou a hora de mostrar ao mundo que você aprendeu algo novo! 🚀

Siga esse guia que preparamos com carinho para disponibilizar o projeto finalizado no seu GitHub pessoal.

Esse passo é super importante para ganhar mais visibilidade no mercado de trabalho, mas também é útil para manter um back-up do seu trabalho.

E você sabia que o LinkedIn é a principal rede social profissional e compartilhar o seu aprendizado lá é muito importante para quem deseja construir uma carreira de sucesso? Compartilhe esse projeto no seu LinkedIn, marque o perfil da Trybe (@trybe) e mostre para a sua rede toda a sua evolução.

Requisitos Obrigatórios

1 - Implemente a função read

Implemente em: src/jobs.py

Para começarmos a processar os dados, devemos antes carregá-los em nossa aplicação. Esta função será responsável por abrir o arquivo CSV e retornar os dados no formato de uma lista de dicionários.

  • A função deve receber um path (uma string com o caminho para um arquivo).
  • A função deve abrir o arquivo e ler seus conteúdos.
  • A função deve tratar o arquivo como CSV.
  • A função deve retornar uma lista de dicionários, onde as chaves são os cabeçalhos de cada coluna e os valores correspondem a cada linha.
📝Exemplo Se o conteúdo do arquivo for:
nome,cidade,telefone
Ana,Curitiba,1111111
Bernardo,Santos,999999

O retorno da função deverá ser:

  [
    {"nome": "Ana", "cidade": "Curitiba", "telefone": "1111111"},
    {"nome": "Bernardo", "cidade": "Santos", "telefone": "999999"}
  ]
✍️ Teste manual Abra um terminal Python importando estas funções através do comando python3 -i src/jobs.py e invoque a função utilizando diferentes _paths_.
🤖 O que será verificado pelo avaliador
  • A função abre o arquivo passado como parâmetro
  • A função retorna uma lista de dicionários
  • A função retorna a quantidade correta de itens na lista
  • Nos dicionários retornados pela função, as chaves correspondem aos cabeçalhos do arquivo

2 - Implemente a função get_unique_job_types

Implemente em: src/insights.py

Agora que temos como carregar os dados, podemos começar a extrair informação deles. Primeiro, vamos identificar quais tipos de empregos existem.

  • A função deve receber o path do arquivo csv com os dados.
  • A função deve invocar a função jobs.read com o path recebido para obter os dados.
  • A função deve retornar uma lista de valores únicos presentes na coluna job_type.
🤖 O que será verificado pelo avaliador
  • A função carrega os dados do arquivo recebido como parâmetro
  • A função retorna a quantidade correta de valores
  • A função retorna os valores corretos
  • A função desconsidera valores vazios

3 - Implemente a função get_unique_industries

Implemente em: src/insights.py

Da mesma forma, agora iremos identificar quais indústrias estão representadas nesse conjunto de dados.

  • A função deve obter os dados da mesma forma que o requisito 2.
  • A função deve retornar uma lista de valores únicos presentes na coluna industry.
  • A função desconsidera valores vazios
🤖 O que será verificado pelo avaliador
  • A função carrega os dados do arquivo recebido como parâmetro
  • A função retorna a quantidade correta de valores
  • A função retorna os valores corretos

4 - Implemente a função get_max_salary

Implemente em: src/insights.py

Os dados apresentam faixas salariais para cada emprego exibido. Vamos agora encontrar o maior valor de todas as faixas.

  • A função deve obter os dados da mesma forma que o requisito 2.
  • A função deve ignorar os valores ausentes.
  • A função deve retornar um valor inteiro com o maior salário presente na coluna max_salary.
🤖 O que será verificado pelo avaliador
  • A função carrega os dados do arquivo recebido como parâmetro
  • A função retorna o valor correto

5 - Implemente a função get_min_salary

Implemente em: src/insights.py

Os dados apresentam faixas salariais para cada emprego exibido. Vamos agora encontrar o menor valor de todas as faixas.

  • A função deve obter os dados da mesma forma que o requisito 2.
  • A função deve ignorar os valores ausentes.
  • A função deve retornar um valor inteiro com o menor salário presente na coluna min_salary.
🤖 O que será verificado pelo avaliador
  • A função carrega os dados do arquivo recebido como parâmetro
  • A função retorna o valor correto

6 - Implemente a função filter_by_job_type

Contagem

Implemente em: src/insights.py

Os empregos estão listados em um aplicativo web. Para permitir que a pessoa usuária possa filtrar os empregos por tipo de emprego, vamos precisar implementar esse filtro.

  • A função deve receber uma lista de dicionários jobs como primeiro parâmetro.
  • A função deve receber uma string job_type como segundo parâmetro.
  • A função deve retornar uma lista com todos os empregos onde a coluna job_type corresponde ao parâmetro job_type.
🤖 O que será verificado pelo avaliador
  • A função retorna a quantidade correta de valores
  • A função retorna os valores corretos
  • A função retorna os valores na ordem correta
  • A função retorna uma lista vazia para job_types ausentes nos jobs recebidos

7 - Implemente a função filter_by_industry

Implemente em: src/insights.py

Do mesmo modo, o aplicativo precisa permitir uma filtragem por indústria. Vamos precisar implementar esse filtro também.

  • A função deve receber uma lista de dicionários jobs como primeiro parâmetro.
  • A função deve receber uma string industry como segundo parâmetro.
  • A função deve retornar uma lista de dicionários com todos os empregos onde a coluna industry corresponde ao parâmetro industry.
🤖 O que será verificado pelo avaliador
  • A função retorna a quantidade correta de valores
  • A função retorna os valores corretos
  • A função retorna os valores na ordem correta
  • A função retorna uma lista vazia para job_types ausentes nos jobs recebidos

8 - Implemente a função matches_salary_range

Implemente em: src/insights.py

O aplicativo vai precisar filtrar os empregos por salário também. Como uma função auxiliar, implemente matches_salary_range para conferir que o salário procurado está dentro da faixa salarial daquele emprego. Vamos aproveitar também para conferir se a faixa salarial faz sentido -- isto é, se o valor mínimo é menor que o valor máximo.

  • A função deve receber um dicionário job como primeiro parâmetro, com as chaves min_salary e max_salary.
  • A função deve receber um inteiro salary como segundo parâmetro.
  • A função deve lançar um erro ValueError nos seguintes casos:
    • alguma das chaves min_salary ou max_salary estão ausentes no dicionário;
    • alguma das chaves min_salary ou max_salary tem valores não-numéricos;
    • o valor de min_salary é maior que o valor de max_salary;
    • o parâmetro salary tem valores não numéricos;
  • A função deve retornar True se o salário procurado estiver dentro da faixa salarial ou False se não estiver.
🤖 O que será verificado pelo avaliador
  • A função retorna o booleano correto
  • A função lança um ValueError se o valor de min_salary for maior que o valor de max_salary
  • A função lança um ValueError se as chaves min_salary ou max_salary tiverem valores não numéricos
  • A função lança um ValueError se o parâmetro salary tiver valor não numérico
  • A função lança um ValueError se as chaves min_salary ou max_salary estiverem ausentes no dicionário

9 - Implemente a função filter_by_salary_range

Implemente em: src/insights.py

Agora vamos implementar o filtro propriamente dito. Para esta filtragem, podemos usar a função auxiliar implementada no requisito anterior -- tomando o cuidado de descartar os empregos que apresentarem faixas salariais inválidas.

  • A função deve receber uma lista de dicionários jobs como primeiro parâmetro.
  • A função deve receber um inteiro salary como segundo parâmetro.
  • A função deve ignorar os empregos com valores inválidos para min_salary ou max_salary.
  • A função deve retornar uma lista com todos os empregos onde o salário salary estiver entre os valores da coluna min_salary e max_salary.
🤖 O que será verificado pelo avaliador
  • A função retorna a quantidade correta de valores
  • A função retorna os valores corretos
  • A função retorna os valores na ordem correta
  • Empregos onde as chaves min_salary ou max_salary tiverem valores não numéricos devem ser ignorados
  • Empregos onde o valor de min_salary for maior que o valor de max_salary devem ser ignorados

10 - Implemente um teste para a função count_ocurrences

Implemente em: tests/counter/test_counter.py

Imagem sobre contar ocorrências

A empresa cliente contratou um relatório que informa a quantidade de ocorrências das palavra Python e Javascript nos dados e, para isso, temos uma implementação pronta em src/counter.py. Durante o desenvolvimento, sofremos com alguns bugs, que já foram resolvidos. Para termos certeza e confiança da nossa entrega, no entanto, e não corrermos riscos, precisaremos de testes automatizados que garantam isso!

O nome deste teste deve ser test_counter, e ele deve garantir que atenda estas especificações:

  • Chamar a função count_ocurrences passando dois parâmetros:
    • path uma string com o caminho do arquivo (src/jobs.csv);
    • word uma string com a palavra a ser contabilizada.
  • Garantir que a função retorna corretamente a quantidade de ocorrências da palavra solicitada
    • A contagem de palavras deve ser case insentitive, ou seja, não diferenciar letras maiúsculas de minúsculas
📌Como seu teste é avaliado O teste da Trybe irá avaliar se o seu teste está passando conforme seu objetivo e confirmará se ele está falhando em alguns casos que deve falhar. Para estes testes que esperemos que falhe, o requisito será considerado atendido quando a resposta do Pytest for XFAIL(Expected Fail) ao invés de PASS ou FAIL.
🤖 O que será verificado pelo avaliador
  • O teste rejeita implementações que não retornam a quantidade de palavras corretamente.
  • O teste aprova implementações corretas.
  • Se o teste não é um falso positivo, ou seja, teste que passa sem realmente testar o código.

11 - Implemente um teste para a função read_brazilian_file

Implemente em: tests/brazilian/test_brazilian_jobs.py

A empresa cliente analisa relatórios em inglês, porém agora ela quer expandir seus negócios aqui para o Brasil e deseja analisar relatórios em português também. No entanto, as chaves do dict que usamos pra organizar os dados devem continuar em inglês. Ou seja: para gerar o relatório, deveremos ler as chaves em português e traduzi-las para inglês para povoar os nossos dados.

Nossa equipe já implementou essa função, a read_brazilian_file, na qual adotamos a estratégia de chamar o método original read, que implementamos no requisito 1, e depois traduzimos as chaves para o inglês. Agora precisamos criar testes para ter certeza que esta tudo certo!

O nome deste teste deve ser test_brazilian_jobs, e ele deve garantir que atenda as seguintes especificações:

  • Chamar a função read_brazilian_file e ela deve receber um parâmetro:
    • path que é uma string com o caminho do arquivo csv em português (tests/mocks/brazilians_jobs.csv);
    • Retorna uma lista de dicionários com as chaves em inglês
📝Exemplo O dicionário: {"titulo": "Maquinista", "salario": "2000", "tipo": "trainee"}

Deve ser traduzido para: {"title": "Maquinista", "salary": "2000", "type": "trainee"}

📌Como seu teste é avaliado O teste da Trybe irá avaliar se o seu teste está passando conforme seu objetivo e confirmará se ele está falhando em alguns casos que deve falhar. Para estes testes que esperemos que falhe, o requisito será considerado atendido quando a resposta do Pytest for XFAIL(Expected Fail) ao invés de PASS ou FAIL.
🤖 O que será verificado pelo avaliador
  • O teste rejeita implementações que não retornam as chaves traduzidas corretamente.
  • O teste aprova implementações corretas.
  • Se o teste não é um falso positivo, ou seja, teste que passa sem realmente testar o código.

12 - Implemente um teste para a função sort_by

Implemente em: tests/sorting/test_sorting.py

Por fim, espera-se que a pessoa usuária possa escolher um critério de ordenação para exibir os empregos. Já temos uma implementação para essa ordenação em src/sorting.py, mas queremos ter certeza de que ela funciona e, principalmente, que não deixará de funcionar conforme vamos implementando novos recursos. Precisamos então escrever um teste!

Esse teste deve se chamar test_sort_by_criteria e garantir que a função funciona segundo esta especificação:

  • A função sort_by recebe dois parâmetros:
    • jobs uma lista de dicionários com os detalhes de cada emprego;
    • criteria uma string com uma chave para ser usada como critério de ordenação.
  • O parâmetro criteria deve ter um destes valores: min_salary, max_salary, date_posted
  • A ordenação para min_salary deve ser crescente, mas para max_salary ou date_posted devem ser decrescentes.
  • Os empregos que não apresentarem um valor válido no campo escolhido para ordenação devem aparecer no final da lista.
📌Como seu teste é avaliado O teste da Trybe irá avaliar se o seu teste está passando conforme seu objetivo e confirmará se ele está falhando em alguns casos que deve falhar. Para estes testes que esperemos que falhe, o requisito será considerado atendido quando a resposta do Pytest for XFAIL(Expected Fail) ao invés de PASS ou FAIL.
🤖 O que será verificado pelo avaliador
  • O teste rejeita implementações que não ordenam corretamente.
  • O teste rejeita implementações que não ordenam em ordem crescente quando o critério é min_salary.
  • O teste aprova implementações corretas.
  • Se o teste não é um falso positivo, ou seja, teste que passa sem realmente testar o código.

Requisitos Bônus

13 - (Bônus) Implemente a página de um job

Implemente em: src/routes_and_views.py

Para fechar com chave de ouro, que tal testar o quanto você consegue aprender de Flask apenas vendo como fizemos as páginas de index e de jobs, e tentar criar uma página que irá exibir todas as informações de um job em específico?

  • A função deve ser decorada com a rota /job/<index>.
  • A função deve receber um parâmetro index.
  • A função deve chamar a read para ter uma lista com todos os jobs.
  • A função deve chamar a get_job, declarada no arquivo src/more_insights.py, para selecionar um job específico pelo index.
  • A função deve renderizar o template job.jinja2, passando um parâmetro job contendo o job retornado pela get_job.
✍️ Teste manual Após criar a view, cheque se, na página que lista os jobs, aparecem links para jobs específicos nos números que identificam cada job. Ao clicar em um destes links, você deve ser levado a uma página que lista todas as informações do job.
🤖 O que será verificado pelo avaliador
  • A rota /job/<index> existe.
  • A view job existe no arquivo src/routes_and_views.py e recebe o parâmetro index (e somente ele).
  • A página de cada um dos jobs deve retornar o status code 200.
  • A página de um job específico (escolhido previamente) deve retornar o HTML exato esperado.

About

Repositório de Análise de Dados da cadeira Ciências da Computação da Trybe


Languages

Language:Python 61.9%Language:Jinja 37.0%Language:Dockerfile 1.1%