From eaa6e45418a16961c4582b2d580cc5eabb9c56f8 Mon Sep 17 00:00:00 2001 From: zeguii Date: Sat, 23 May 2026 01:15:18 -0300 Subject: [PATCH 1/2] 22/05 --- Guia2/README.md | 155 ++++++++++++++++++ Guia2/pytest.ini | 3 + Guia2/requirements.txt | 0 Guia2/run_tests.bat | 2 + Guia2/src/__init__.py | 1 + .../src/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 274 bytes Guia2/src/folha_pagamento/__init__.py | 4 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 358 bytes .../__pycache__/desenvolvedor.cpython-312.pyc | Bin 0 -> 419 bytes .../__pycache__/estagiario.cpython-312.pyc | Bin 0 -> 413 bytes .../__pycache__/funcionario.cpython-312.pyc | Bin 0 -> 3389 bytes .../__pycache__/gerente.cpython-312.pyc | Bin 0 -> 407 bytes Guia2/src/folha_pagamento/desenvolvedor.py | 36 ++++ Guia2/src/folha_pagamento/estagiario.py | 26 +++ Guia2/src/folha_pagamento/funcionario.py | 77 +++++++++ Guia2/src/folha_pagamento/gerente.py | 34 ++++ Guia2/tests/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 156 bytes ...desenvolvedor.cpython-312-pytest-8.3.5.pyc | Bin 0 -> 5824 bytes ...st_estagiario.cpython-312-pytest-8.3.5.pyc | Bin 0 -> 5706 bytes .../test_gerente.cpython-312-pytest-8.3.5.pyc | Bin 0 -> 5809 bytes Guia2/tests/integrity.py | 32 ++++ Guia2/tests/test_desenvolvedor.py | 44 +++++ Guia2/tests/test_estagiario.py | 38 +++++ Guia2/tests/test_gerente.py | 47 ++++++ 25 files changed, 499 insertions(+) create mode 100644 Guia2/README.md create mode 100644 Guia2/pytest.ini create mode 100644 Guia2/requirements.txt create mode 100644 Guia2/run_tests.bat create mode 100644 Guia2/src/__init__.py create mode 100644 Guia2/src/__pycache__/__init__.cpython-312.pyc create mode 100644 Guia2/src/folha_pagamento/__init__.py create mode 100644 Guia2/src/folha_pagamento/__pycache__/__init__.cpython-312.pyc create mode 100644 Guia2/src/folha_pagamento/__pycache__/desenvolvedor.cpython-312.pyc create mode 100644 Guia2/src/folha_pagamento/__pycache__/estagiario.cpython-312.pyc create mode 100644 Guia2/src/folha_pagamento/__pycache__/funcionario.cpython-312.pyc create mode 100644 Guia2/src/folha_pagamento/__pycache__/gerente.cpython-312.pyc create mode 100644 Guia2/src/folha_pagamento/desenvolvedor.py create mode 100644 Guia2/src/folha_pagamento/estagiario.py create mode 100644 Guia2/src/folha_pagamento/funcionario.py create mode 100644 Guia2/src/folha_pagamento/gerente.py create mode 100644 Guia2/tests/__init__.py create mode 100644 Guia2/tests/__pycache__/__init__.cpython-312.pyc create mode 100644 Guia2/tests/__pycache__/test_desenvolvedor.cpython-312-pytest-8.3.5.pyc create mode 100644 Guia2/tests/__pycache__/test_estagiario.cpython-312-pytest-8.3.5.pyc create mode 100644 Guia2/tests/__pycache__/test_gerente.cpython-312-pytest-8.3.5.pyc create mode 100644 Guia2/tests/integrity.py create mode 100644 Guia2/tests/test_desenvolvedor.py create mode 100644 Guia2/tests/test_estagiario.py create mode 100644 Guia2/tests/test_gerente.py diff --git a/Guia2/README.md b/Guia2/README.md new file mode 100644 index 0000000..56985d6 --- /dev/null +++ b/Guia2/README.md @@ -0,0 +1,155 @@ +# Guia 2 — Sistema de Folha de Pagamento (RH) + +## Contexto + +Você faz parte da equipe responsável por manter um módulo de **Folha de Pagamento** dentro de um sistema de **Recursos Humanos (RH)**. + +Esse módulo calcula informações básicas de funcionários de diferentes cargos, como: + +- nome +- matricula +- salario_base + +Atualmente o sistema possui uma hierarquia de classes para representar funcionários, mas carece implementar as subclasses de acordo com o diagrama UML abaixo: + + -------------------------------- + | Funcionario | + -------------------------------- + | - nome | + | - matricula | + | - salario_base | + -------------------------------- + | + dados_basicos() | + | + gerar_contracheque() | + | + calcular_salario_liquido() | + | # calcular_bonus() | + | # calcular_descontos() | + | # calcular_adicionais() | + -------------------------------- + ▲ + ----------------------------------------- + | | | + | | | + ----------------- ----------------- ----------------- + | Desenvolvedor | | Gerente | | Estagiari o | + ----------------- ----------------- ----------------- + | linguagem | | setor | | curso | + | senioridade | | qtd_equipe | | carga_horaria | + ----------------- ----------------- ----------------- + +Seu papel é implementar as subclasses passando nos testes propostos. + +--- + +## 1. Desenvolvedor + +### Atributos adicionais + +- `linguagem` +- `senioridade` + +### Regras + +#### `calcular_bonus()` + +O bônus depende da senioridade: + +| Senioridade | Bônus | +|-------------|----------------------| +| junior | 5% do salário base | +| pleno | 10% do salário base | +| senior | 15% do salário base | + +--- + +#### `calcular_descontos()` + +Desconto fixo de **8% do salário base**. + +--- + +#### `calcular_adicionais()` + +Adicional definido pela linguagem principal: + +| Linguagem | Adicional | +|----------------|-----------| +| Python | +500 | +| Java | +400 | +| JavaScript | +350 | +| Qualquer outra | +200 | + +--- + +## 2. Gerente + +### Atributos adicionais + +- `setor` +- `qtd_equipe` + +### Regras + +#### `calcular_bonus()` + +O bônus depende da quantidade de pessoas na equipe: + +| Tamanho da equipe | Bônus | +|-------------------|---------------------| +| até 5 | 10% do salário base | +| de 6 até 10 | 15% do salário base | +| acima de 10 | 20% do salário base | + +--- + +#### `calcular_descontos()` + +Desconto fixo de **12% do salário base**. + +--- + +#### `calcular_adicionais()` + +Adicional por responsabilidade: + +| Quantidade da equipe | Adicional | +|----------------------|-----------| +| equipe > 10 | +2000 | +| equipe > 5 | +1000 | +| caso contrário | +500 | + +--- + +## 3. Estagiario + +### Atributos adicionais + +- `curso` +- `carga_horaria` + +### Regras + +#### `calcular_bonus()` + +Bônus fixo de **3% do salário base**. + +--- + +#### `calcular_descontos()` + +Desconto fixo de **2% do salário base**. + +--- + +#### `calcular_adicionais()` + +Auxílio baseado na carga horária: + +| Carga horária | Adicional | +|---------------|-----------| +| até 20h | +150 | +| até 30h | +250 | +| acima de 30h | +350 | + +--- +995b5983a8b684cba7bbc7f802c760906f0d690c1e90bf440631cfe486082eb3 \ No newline at end of file diff --git a/Guia2/pytest.ini b/Guia2/pytest.ini new file mode 100644 index 0000000..97a0030 --- /dev/null +++ b/Guia2/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +pythonpath = src +testpaths = tests \ No newline at end of file diff --git a/Guia2/requirements.txt b/Guia2/requirements.txt new file mode 100644 index 0000000..e69de29 diff --git a/Guia2/run_tests.bat b/Guia2/run_tests.bat new file mode 100644 index 0000000..a2937ce --- /dev/null +++ b/Guia2/run_tests.bat @@ -0,0 +1,2 @@ +pytest -v +pause \ No newline at end of file diff --git a/Guia2/src/__init__.py b/Guia2/src/__init__.py new file mode 100644 index 0000000..5d96e84 --- /dev/null +++ b/Guia2/src/__init__.py @@ -0,0 +1 @@ +from folha_pagamento import Estagiario, Gerente, Desenvolvedor, Funcionario diff --git a/Guia2/src/__pycache__/__init__.cpython-312.pyc b/Guia2/src/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..73e61bee553995b8bd027336b80c464892268f93 GIT binary patch literal 274 zcmXwxJx&8L6ol>dhMz>MT!0H~LqP{ZH2kE9AT%^9OO};=BnJPiZ0|}r2@MzEEVNW^ zD5&U=(xu{Af|2HX^Q6(dSJjxHUf0v7TfATS`B(85wnrFVNK0C(iJ=WOMN=5oFjF=q zC7YsV-?>_sX?z``Tq)_5OZzkMU?ZgJ3If={=>b~j)8wYNOXX}X-PNNseRO&)MJHF% zVBdL$TfWQ~W$Yo|$QDU%-+e!o~`3lE*+vtG#)9{iFEp{$BR h9Cw@D!MSm5ui?T^aEYQr4nK@i`bp*=WbO~~{{@WEN-zKb literal 0 HcmV?d00001 diff --git a/Guia2/src/folha_pagamento/__init__.py b/Guia2/src/folha_pagamento/__init__.py new file mode 100644 index 0000000..63a2be0 --- /dev/null +++ b/Guia2/src/folha_pagamento/__init__.py @@ -0,0 +1,4 @@ +from .funcionario import Funcionario +from .estagiario import Estagiario +from .desenvolvedor import Desenvolvedor +from .gerente import Gerente diff --git a/Guia2/src/folha_pagamento/__pycache__/__init__.cpython-312.pyc b/Guia2/src/folha_pagamento/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c9423a903a7dca7b90ee06f3f9aa6224229a09cf GIT binary patch literal 358 zcmYjMyH3L}6t(lLQUYRULJVYKKuid+@TgcQ3rl3lvKluH*l}bhk-G2^Ed2()g+GWC z7A7{NZk@O;<#DBZea^AYx%O)uM+oX^w)5}|=es38XlRLxg|GpVvh@N>Nl$@Z6K W7sjWHG49bpkM?_X_=fiM7N}opPh`0O literal 0 HcmV?d00001 diff --git a/Guia2/src/folha_pagamento/__pycache__/desenvolvedor.cpython-312.pyc b/Guia2/src/folha_pagamento/__pycache__/desenvolvedor.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4184750c23ee8739353eb22bf091220842d63946 GIT binary patch literal 419 zcmZ8dJx{|h5WP!MDgB6$SXo)Jbbt*Z77*Q97M948WyNj@Byn&)q^_v{p}zs~Q}_cY z5@KLtLu5eegq^ekagv|kv+tgL_w0EC(DAm|yM566yAiu^wxl`KWDOiR#*kou2o_9$ zTPxu9lhtJf*3$8NA4d3C4=>9!jAY7GB*QMDL)?mHq{$it1js?xqHopSg~&x($+!|+ zs;O_+E~P0;1f}(W(nRtyHhe_seaYhP<`EiWxtX4ykn3EioK!3>1kql1h0Ms+Y-Sc! zB9mlNM(l{>DkO6m-!Pi7g|<%%N%-HV$JtW#v}p^5|Lhn8`c&MHQTtST`OnG)6z^N-`DVIBjPI@f4hkNFVN7|`~bVbXleie literal 0 HcmV?d00001 diff --git a/Guia2/src/folha_pagamento/__pycache__/estagiario.cpython-312.pyc b/Guia2/src/folha_pagamento/__pycache__/estagiario.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..065df0dbcb89a046b855bcc4ae46a3e63fcf4c99 GIT binary patch literal 413 zcmZ8dJx{|h5WP!MDNP$8v9hvc=>Qu-EPQl8qAVmI$Vy;D`PSz&(e~U6RvJcQIN~Y#4IX# zA;`E&*d9?bB2$rGGg`2jE}xfz@ZWbw#a#Au#TE=v1{Uz*xY7)&JvX1*`B!5!{cBj- nn@rg^tThfaTe*i_A4k&H(#%3_YxuAc@fG&JT*Uq-XlOk@grQ}} literal 0 HcmV?d00001 diff --git a/Guia2/src/folha_pagamento/__pycache__/funcionario.cpython-312.pyc b/Guia2/src/folha_pagamento/__pycache__/funcionario.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a87ac567fc05396055a7991980519217e7f7a3ed GIT binary patch literal 3389 zcmbsrO>Yxd@a>o5&vkHc8=E9{5}+}KfKs?rh|&T@&^A;JJQaZH#6^J zKHq*Hi-ifm!H?tDJ`WP|J5IVFbcpsLAXbS&6hC z<>vzmzrxQ7YCsWGZk|;FEBw>Wve`bD+vnj1Z7vVGK@T?s>%+hc!EOs*(jX zBWvrAz{YHO{cAnDs4HsLP-(WTF34u_raqbDt?);(R#DGUs#8mlY$t`KZ7;9GL_H}AOpRZ1$g%UnK$#7;RqvtQ`Ss1e^xcFoBCq@!%LU&lc>6==g(J) z@>JfSh5Wp(U6rLpc|k6zWmC`3ZwG90amflwQn6e#C8@gC6Uxah7f&@V0=i9piVysp z7}^+~tS63cM34R&AGD{(>xmN^(G#1ISJy^=i0rd@Z`Bj0H=?IElc~G>r{QLL9ENyv zICq!-F_><{Zo~>u)vVBR!3_{Fk+zc}4Fn_wxdx*jX2=s}I>*o`2%az$qh{d3EbRwu zd#&2LBoygu3?+7A~pjsXHE?Hydb@Zdr-HT>1c7bDG~Y-8w1ZRkid znOeQ_;7TKTxRyM;6%zWxEh2=%y>3Jo+HSlJ#0%VrIzH&W09D|F^SUpUN6V*yZNmqy z2E2eX#K~UX?kbj8kTq;=RGQPv6~h{E=dx0?8+*~P5-w9wje-tc#OQJBpsUkOG_81} z0!_5K-|OM$X&r_u8|MIlv!nfu=x{AM+!PZHakM6m*2VEHj*0ExM8?6Ic(5)`Yzb^E z*9wsMKtnuG6A#qI*S7k&*hGulH3C=J0R^1`3VI3!TdNa#!HIa-6X=i|Un}klV=m;`WFKxa)ZK|@ zkjf$&MKp%U*A}hBf=VIFFniz^>8g68qE<(|nb9jh4*M9N0O~0~Z{2yTv5}mpB`501 zL(TL^BRy41Pu0`Mp=ukcW3|+=dTOef8E<4x)-osSnNwSPLRhe&-3k^Cb<%|gVikT6 z?4o(nW0q}tHSM*-&2ZbjXJCCBixzAMMteI0NOn1h;(w^$g|>5d`piAcjoW!#_&TDV z#|@Y-eN+~7tC?NR+D@1EKxzA|>0H822`el~C0(g#(0r|^B;BaUn$wCc4t|dlZc zE2PCng+psIEds-1XZTiVJO<-t^kicF%H1<%y*P_*80m+g?9PI?wR>BQ$0Jpp?7?_^-Lwm61iej($3^A{N=c7OaI If}_3rzZ)*OL;wH) literal 0 HcmV?d00001 diff --git a/Guia2/src/folha_pagamento/__pycache__/gerente.cpython-312.pyc b/Guia2/src/folha_pagamento/__pycache__/gerente.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..444c7e28d7fdbdb5546407bbd4222630c1e9431c GIT binary patch literal 407 zcmZ8dJx{|h5WP!MHT{T?SXo)Jbbt*Z77$^gEG&^F%ZlALki@}BDs}IF=x;#$6#f8; z#Kgpg$bi%dJ86Z)Nq&CMzI*oFtLF_tM}Kkfu+;m95&Ljas#><@mi%BYdn!*Hsq9GGi*1QJ2sm?nE=zWCH?1)W+U zX~t4PX+5MgmApy}A5;2Nv820shQ^p}Z!XWseIZmqmMkd+xe~==DRXi+otj0J$R!D? zn4OS9MPw$E1*18eYx}H}WZpeG$ychU?OHITFtCO<$5m!T?Ya5c(LaO9?5|a2?=#iF ku(oid+15Spnz&G&mSzgYp@uIT5#QnT$3+}`gNC-|7wB_hPXGV_ literal 0 HcmV?d00001 diff --git a/Guia2/src/folha_pagamento/desenvolvedor.py b/Guia2/src/folha_pagamento/desenvolvedor.py new file mode 100644 index 0000000..01da94f --- /dev/null +++ b/Guia2/src/folha_pagamento/desenvolvedor.py @@ -0,0 +1,36 @@ +from folha_pagamento.funcionario import Funcionario + +# Desenvolva a classe Desenvolvedor aqui. + +class Desenvolvedor(Funcionario): + def _init_(self, nome, matricula, salario_base, linguagem, senioridade): + super()._init_(nome, matricula, salario_base) + self.linguagem = linguagem + self.senioridade = senioridade + + def calcular_bonus(self): + nivel = self.senioridade.lower() + + if nivel == "junior": + return self.salario_base * 0.05 + elif nivel == "pleno": + return self.salario_base * 0.10 + elif nivel == "senior": + return self.salario_base * 0.15 + + return 0.0 + + def calcular_descontos(self): + return self.salario_base * 0.08 + + def calcular_adicionais(self): + ling = self.linguagem.lower() + + if ling == "python": + return self.salario_base + 500.0 + elif ling == "java": + return self.salario_base + 400.0 + elif ling == "javascript": + return self.salario_base + 350.0 + + pass \ No newline at end of file diff --git a/Guia2/src/folha_pagamento/estagiario.py b/Guia2/src/folha_pagamento/estagiario.py new file mode 100644 index 0000000..e10fd20 --- /dev/null +++ b/Guia2/src/folha_pagamento/estagiario.py @@ -0,0 +1,26 @@ +from folha_pagamento.funcionario import Funcionario + +# Desenvolva a classe Estagiario aqui. + +class Estagiario(Funcionario): + def _init_(self, nome, matricula, salario_base, curso, carga_horaria): + super()._init_(nome, matricula, salario_base) + self.curso = curso + self.carga_horaria = carga_horaria + + def calcular_bonus(self): + return self.salario_base * 0.03 + + def calcular_descontos(self): + return self.salario_base * 0.02 + + def calcular_adicionais(self): + + if self.carga_horaria <= 20: + return self.salario_base + 150.0 + elif self.carga_horaria >20 and self.carga_horaria<=30: + return self.salario_base + 250.0 + elif self.carga_horaria > 30: + return self.salario_base + 350.0 + + pass diff --git a/Guia2/src/folha_pagamento/funcionario.py b/Guia2/src/folha_pagamento/funcionario.py new file mode 100644 index 0000000..0f8dccc --- /dev/null +++ b/Guia2/src/folha_pagamento/funcionario.py @@ -0,0 +1,77 @@ +from abc import ABC, abstractmethod + +class Funcionario(ABC): + def __init__(self, nome: str, matricula: str, salario_base: float): + if not nome: + raise ValueError("Nome inválido.") + + if not matricula: + raise ValueError("Matrícula inválida.") + + if salario_base < 0: + raise ValueError("Salário não pode ser negativo.") + + self._nome = nome + self._matricula = matricula + self._salario_base = salario_base + + # --------------------------- + # Propriedades comuns + # --------------------------- + @property + def nome(self) -> str: + return self._nome + + @property + def matricula(self) -> str: + return self._matricula + + @property + def salario_base(self) -> float: + return self._salario_base + + # --------------------------- + # Métodos concretos + # --------------------------- + def dados_basicos(self) -> dict: + return { + "nome": self.nome, + "matricula": self.matricula, + "salario_base": self.salario_base, + "cargo": self.__class__.__name__ + } + + def calcular_salario_liquido(self) -> float: + return ( + self.salario_base + + self.calcular_bonus() + + self.calcular_adicionais() + - self.calcular_descontos() + ) + + def gerar_contracheque(self) -> dict: + return { + "nome": self.nome, + "matricula": self.matricula, + "cargo": self.__class__.__name__, + "salario_base": self.salario_base, + "bonus": self.calcular_bonus(), + "adicionais": self.calcular_adicionais(), + "descontos": self.calcular_descontos(), + "salario_liquido": self.calcular_salario_liquido() + } + + # --------------------------- + # Contrato abstrato + # --------------------------- + @abstractmethod + def calcular_bonus(self) -> float: + pass + + @abstractmethod + def calcular_descontos(self) -> float: + pass + + @abstractmethod + def calcular_adicionais(self) -> float: + pass \ No newline at end of file diff --git a/Guia2/src/folha_pagamento/gerente.py b/Guia2/src/folha_pagamento/gerente.py new file mode 100644 index 0000000..354df49 --- /dev/null +++ b/Guia2/src/folha_pagamento/gerente.py @@ -0,0 +1,34 @@ +from folha_pagamento.funcionario import Funcionario + +# Desenvolva a classe Gerente aqui. + +class Gerente(Funcionario): + def _init_(self, nome, matricula, salario_base, setor, qtd_equipe): + super()._init_(nome, matricula, salario_base) + self.setor = setor + self.qtd_equipe = qtd_equipe + + def calcular_bonus(self): + + if self.setor <= 5: + return self.salario_base * 0.10 + elif self.setor > 5 and self.qtd_equipe <=10: + return self.salario_base * 0.15 + elif self.setor > 10: + return self.salario_base * 0.15 + + return 0.0 + + def calcular_descontos(self): + return self.salario_base * 0.12 + + def calcular_adicionais(self): + + if self.qtd_equipe > 10: + return self.salario_base + 2000.0 + elif self.qtd_equipe > 5: + return self.salario_base + 1000.0 + + return self.salario_base + 500.0 + + pass diff --git a/Guia2/tests/__init__.py b/Guia2/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Guia2/tests/__pycache__/__init__.cpython-312.pyc b/Guia2/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..65afc7ba052841abcb210e076b4cc2512b3b915a GIT binary patch literal 156 zcmX@j%ge<81i23USs?l`h(HIQS%4zb87dhx8U0o=6fpsLpFwJVSvy7&-6@X`dxTLuH@qeV)apbnHw2>;9lJyg#itJiOilTA?8ASs@D6!(Ml$9wi zJG)dRg#_f*KyxXOo719)pePC(LJOnqAwBm}AcvBcY#9p_b0r~dL%$qkeyPR*|<0oxxSpwygg^tB3jgWt0MU+&i>^=qM4zY+O70HamuJV#n zkR`ID&ZH#Xqs?g0BNx+4nVF14Y;EzFa1>uHCRf%d>C4^%j2f)GoWTZ&n<0 zaMrgy-(xawC6_x;UJcszw9qzijf?VL0Qw&^(%Gt3e}-+ z?G)_Waj9dOmfc^rX~8b}6|-n4h8$>%73^F1#m}+an=oYB0%OAZpP(LSeE7l;D}SCS z;NC=uZryj`soo(~sY>#qk5uIKvi|G2mZiM^ZTT0Ik{aoqfz>DfX1-g$%U_=Ex-C+9oN zB`ZV8$}q2R-=oRO>mEX)TNH|?DtMV~mfiDw*`@i!oud6pcy+iz+|&(F>bi0ForXTVt>Wil*uZO%Y^cNU zkMr7QtZt!k4{v_J21Wz80`Bj=6Acq;(&&*o%s5(zUJI}X+&_C|{F-x*EJDNnQj>sX zlHf~Cwj@TqCPb{MRi&yjE~bE*DM7psB=3|j-r-~sPTc+iv_s}8I4Z$B)yEaGvdE$X zQR7#!CdRzje-k>!Bm+Xkmj98CNQeV$C2{T#u#*pI7tsl3{{P;2M0;SU)|8<~#j{G> znY0q5;I#f7^4i0o`eNaj3X&VGYH#J`Z8*2c{O)ots?>B+z`+h zn}>{Sa4ceOv?h86-JC`7DvE9t=TLkF#aB^$4aIp7f|5Ph08z#sGL9r+_&Nu6$jlry z(3mlt^D#HLr*^R!A&)Uaik0T)ofVgkf*;(t_g4_>L0r602@T>xh^K*u}hhab%6Ce&9PLvfLAO zYAov1!l*OtAC{PD@ir0HFzQTFQowQgIpHXN<4%H(=qidlj|q$T6i^J2Ddx5h?AUaF@D4zSEGXlsye}|?>no|T*$1ev6o}~~VJRv;C__1%! zJo|qv52-QyTSl+K7$lPSTM+Byad!{T3eSF>q2x)&`7kBSHS}CvodCJ14}ntGhwiU5 z^oea1KM%tOUW;Tyoj{tP#b&H-p>d8kKVSo+0bBw1_gA;G?D>9k#It5NLczpm?-ERk#sB8bU+ALTz^219i!y zHv=91HGuyCeCn*(ET3kfBf~JejTF;7wkme_pJl$e}RqpeM{O^hI_q7zr$oId?-Es3 wKFcc7$gU3B4r)(ZW$A|Wg#n{aiFOGFXfU8%maa*=9iZ-THJg$yOKiFS1}LSA7ytkO literal 0 HcmV?d00001 diff --git a/Guia2/tests/__pycache__/test_estagiario.cpython-312-pytest-8.3.5.pyc b/Guia2/tests/__pycache__/test_estagiario.cpython-312-pytest-8.3.5.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bdcfb1cf5898e0a23351b53293c72bba75a5ca35 GIT binary patch literal 5706 zcmeHL(Qn(v8NVY>lq}hC;xw6)bg9~=h3U4c?Zio&+Nqtkt2cOQ*I^i77$X>ww&}>C zcBHe|l>lc=u|4)-XkLn;7`DQOfx?gZANDXQa^r%)unxl>i~@yQ@5xX5zB`hpQlmD4 z0O>;s@#FX1{l1UKlkUgg>F*sKSpvuEbmwe7MaX|Jhz^LwvAqVD+r%OkEs+T-uF9NR zR4AEa6DcZtv?M z;UW%;T8gDw%u20>bMQ-|YgYp8HItWIFHp}7o}U)T%Iy&-U!JzhGf>{#JPoZJYp#%O z1ngXX?c(IGJezxy*Uge|Prhz@*L=4!`Sx3H;c0NY;!eIf@0bIVzU}#*um*VHfD4s{ zAiEp#4k(Ia@_qzniTqC^?Z-cu`8f6Q_2ufFcbd78Ive3R=qtug13?>{;z|Dsb9S3l z$t*P7f7GZ#sxsIPNHk9s#e(|jH8ySD%I4r9`LlP_5t;d`_Zq4%xcLT z>03%wo1&JASyRd?3tO3wBNWH1_&r9EyhdZXPP}7@`t7YKjH+Zcd~TjZ9{Mh1nOZDS zbuTQ9s_uhR4v14D9NhW){p2hjY3d_w5x&t{+S06aHSJIlW&9)2+$QE`kCk7|M3tiJ z?}15f&>DqPfm4H1g_G4%3q;RcnZ9%S{V#uU=g+UM&>dxXSf`7%XL>3N=X5XoZs_EP z^XLskP2hx0eY#gDnx*1=$>hdWw>)e!$9#=!N+&LB3}~ zvf~<8P0!BObg}eSv_P#a^r0C*a}Lb~G%p3Lve4hR(`kCJ+p4sRnL zpg$R$O$O(a!OL=JVNOfZpzM-&>mO)|&UyH=&qoKxr5tpM2@v0wG3DHF`3umBT;}}) z%o6z`cWfhfrja{SXJcTSxo5#y#%S&2M*mo&e@w>U_M%${KrbN2HW+^HMJ+OnZG(;d z@uG~HyY4!o&&cMxA~W`v!{)ex9D%qARDi(<7c2CK_l}`)ksnAJzSAE_8YY3v?)A!v zUt|Y(Jv~B_e)q9Y-~9LDpI+si@F2j^Hy@CrE!!))W#4^BJk9Z~#Jka)z=36hu9$w~ zTk%ua|2P_ynOumsC(z5Ic@oW2Xr4xM2FzZp)g@RfDk_Pq53q+3pCGQDMy{vM#=$mo zz2GccVAdu!2FDwN<1z-ffNmWC1wf8(F#Oz$T4Wg81{+7>LP&GhT}O0}Y`!ZpV}IF_ zZfxZUq6#n=;bMis@ZK?0I#5s$*J8eC@@dnUaXISV=S|Bg!g~Z>Kekt~xoNq&rYoC| z!5nOU2nKxof$#z8<9D*TBYci80zN3)aiTYW0}2lCpeYHz0H%n_H9BI=UXV(bR*4by zp|0Iat*W4F)ks5vc4bvXDArUp<$aY#( zrOxY~6i{6eVs{~|FphGVA4P);0@dRAokIzo2x^lbhaRA*j+S*59F18kD(rX%Wh^}- z#>6k-jW42k2F{$3I8erZ;kWosEKR=AHwm4)#R|M>iOLK8spp7~2LLMT$d6bJtx*v@V

6G=KL4lB@x;D`T@x%+8>sj-_ARhySssHVVq3#!sV~P zy5qxWB$tSVA9TkIa$mgz(@0v<$m>|Sl|lFjwvB@EaN&fEAvbf~f-vs8r*XD#hW`Yh zPhrmAz$}r^pLkNx#21}UFO3PVC^T|~IvWDp%=Lj&&-JarHg0Hx;pelkK}NA{upwj$ zL^OBZbp#h=^Iee`CrAg%ufZNIOpDwk=pGvqJfR;6GSLoPNX6iUA@}SBN#&q_3f%r3 zcYN4?$4x;xY!mYxXfh>GJznGtCLl<|R@a~Bwwz_$@^X}q0h=@VwIB!Ef7sCb+*z~* z#fs_U_$Qedm6+_E%+Q=`&6n&;{B7vKf51Hae{xHul>Up5Tjaftf0C118c{NTIDPZ< z*NQ?%>9$Ig!&}1rCach&QnWv(TUkV%x_N4Yb~k8u{lqKZkn|;Go1_)>>%$7YOt+7K NyCvN$qr+k#{|B!WW?TRO literal 0 HcmV?d00001 diff --git a/Guia2/tests/__pycache__/test_gerente.cpython-312-pytest-8.3.5.pyc b/Guia2/tests/__pycache__/test_gerente.cpython-312-pytest-8.3.5.pyc new file mode 100644 index 0000000000000000000000000000000000000000..42c8ece72bf1eed6daec55129e5b0f65754100e6 GIT binary patch literal 5809 zcmd6rO>7)V6@aUMre{3uzc`R}5|Xud*Rgw@_%Dus7Hnt5;sAmyECD2AX=qQkz2nTd zXRF(bZDu3~g4pBUvLFr-0+h&?h|_X`11H3Rnb@(TmJlm(01F9u<2~iXdsSWCZD+!m zDAH1ze*LQIy;oK3uCHJD&rMBf0_FSPYgyb*5b}4dhyrz1_8-CR7O{vW<;jf1?s7rN z$`UE4GYN_JXfqo0$oXU;HItHvtu3|%{;`{-+$0-8eI^YyCt{s}x_I)*HcMR~R^pe^ zhRpjcEf%NAO5P+h&HqER6hv!?MN7w`wOBetYh9I$#$6oj>RriCUa_gYAl0CSDn87oFKF%Q$Kd^6q=gzfzgPZ!Lih7Ca(6@H_9nZ?x?=0tv z_W7bsv#{c2GoP7rmX=*ZGvr;I;6Hx;Gc3QGGGy8Sb=m>~`ZVmj$jTp~Zx>%HdW`pB z^uX^=*!LOiLy^UZqJ+=$Yw$?*V(Qq`Ck0a6DEPQ$maGmQ>Q_;qQn(^YTUz-BLVU3oDC_LW}NVtapj~ z*;xGM$UF~yM(Z_)aSM$MZ~PTqRKeQ~<)o!q$x<>Wv0BPIE}lVbE%?$LDy5VdSKNODh+2`#DqM-Own~f??BU1q#DpQO zeZ8xvxH@dO=^qA4$3zEeL!t?kplQHx`?6*}yPP*E-vsG$kC85SOmLSG!)2SxPuVVP z7t?a?s=iWO9Y8UJVi?89<7U%^o$Rr3#tau5#|+(1N88PBbWIo~=Vazg*Y=wa4(q2c z7guqYXH4oJ%Rpxy_dm@#g`!DqzY)4KbIZBBms@guE$@JZ>$hjzx1Hs@#Y{5`d1nsx z@{(Dw{f3Nd&I2im)Ng*BO)cjveThcCvU#b976}LK=|7$p_@?SM%!vXLvA+wX22To z5wP#cuQ>n6A~YN>WeJ!j3C@&dOJek^LB_ILQc5c0V*==z5afGba!+`{cZrZifsDoS!79rsPVg)6JuW#zXl~Eq5&x)%l}GABt;!tN$meRcJdMJLQ28N z|KBSQsShmGYO)kR#H_@gO^x*IsVtR%r7~O^Tnb!jIl;KP@Zs5?{Og+^{(g#Lb^(07 z@r-=6Y&YvHd5#+~wg*Fv0*+s0>jv9=r%t#^#Gg+HVWt8_tQogkfGm(S_n1if$B;O%Q6Jcoju22!YEB z*w6y5G1GV8=kZfa+6f@1t=T;m#0dbJZ?q5KxlaG*p zT~)oSqE3U{)Vo2sGYsNh_s-CCb!eK`LG4Ag0tUTcIlZIeZ(FqRYACDfG{O;0HY0Tl zt-E;hedZbJcZRtdN{cMVg8URyTKYPO+WBc8=kvk*v}Sf%R)E%u zAR`c2Ey;|-kc&bF8nLeyg(aXbW}x5`qpAA|WpYD|6mXV|on$S!4E0)P*|H3@kV9H1kiSWc7Ql_Vw18X> zXn{GO6r)ArQ>I0t4h6z}SjR4;ilsfb6@~d?U0Q^eKnpmd2Itj;m9iR2iGUW`k!hg` zN{D+v3(T*SvI==s`syxjo?JVm9D*C)eMWAG>?oguf9zOJlwQT*!47dxp+$R0i$kG~ zjEp2l2BsuWrv>hrfEMxN-=Q&s!(V2MeiiI7-Ew~oVx2rZd5RtWK5FR>PJF#py|+s(JIPZHjw`Q~BGRq7pB9=Wqil;a>EB3@6r@l~dtmV8tNv}Z% zCQ$BsAodhVlKw`>P4eTWzmgaBG$N;ddiKWIk7ZdJ*;k0%x`*0c8rx6bIK3maSEcsK y$&p7SIWF&$q^x}0sz?L-$3WXd?NOsFU6Gz}7z2mT3kO-63LH>NtI}(1rvCvcfpkFt literal 0 HcmV?d00001 diff --git a/Guia2/tests/integrity.py b/Guia2/tests/integrity.py new file mode 100644 index 0000000..6d3ebd9 --- /dev/null +++ b/Guia2/tests/integrity.py @@ -0,0 +1,32 @@ +from pathlib import Path +import hashlib + + +def gerar_hash_pasta(pasta=".", extensao=".py"): + arquivos = sorted( + [ + arquivo + for arquivo in Path(pasta).rglob(f"*{extensao}") + if arquivo.name != "integrity.py" + ] + ) + + print(arquivos) + + hash_global = hashlib.sha256() + + for arquivo in arquivos: + # inclui nome/caminho do arquivo no hash + hash_global.update(str(arquivo.relative_to(pasta)).encode()) + + # inclui conteúdo + with open(arquivo, "rb") as f: + while bloco := f.read(4096): + hash_global.update(bloco) + + return hash_global.hexdigest() + + +if __name__ == "__main__": + resultado = gerar_hash_pasta() + print(resultado) \ No newline at end of file diff --git a/Guia2/tests/test_desenvolvedor.py b/Guia2/tests/test_desenvolvedor.py new file mode 100644 index 0000000..0ee0137 --- /dev/null +++ b/Guia2/tests/test_desenvolvedor.py @@ -0,0 +1,44 @@ +import pytest +from src import Desenvolvedor + + +@pytest.fixture +def desenvolvedor(): + # Instância base com salário 5000, linguagem Python, senioridade pleno + return Desenvolvedor("Ana", "123", 5000.0, "Python", "pleno") + +# ---- Testes para calcular_bonus() ---- +@pytest.mark.parametrize("senioridade,percentual", [ + ("junior", 0.05), + ("pleno", 0.10), + ("senior", 0.15), +]) +def test_bonus_por_senioridade(desenvolvedor, senioridade, percentual): + desenvolvedor.senioridade = senioridade + esperado = percentual * desenvolvedor.salario_base + assert desenvolvedor.calcular_bonus() == esperado + +# ---- Teste para calcular_descontos() ---- +def test_desconto_fixo(desenvolvedor): + # 8% do salário base + assert desenvolvedor.calcular_descontos() == 0.08 * desenvolvedor.salario_base + +# ---- Testes para calcular_adicionais() ---- +@pytest.mark.parametrize("linguagem,adicional_esperado", [ + ("Python", 500), + ("Java", 400), + ("JavaScript", 350), + ("C++", 200), + ("Ruby", 200), +]) +def test_adicional_por_linguagem(desenvolvedor, linguagem, adicional_esperado): + desenvolvedor.linguagem = linguagem + assert desenvolvedor.calcular_adicionais() == adicional_esperado + +# ---- Teste integrado de salário líquido ---- +def test_salario_liquido_pleno_python(desenvolvedor): + desenvolvedor.senioridade = "pleno" + desenvolvedor.linguagem = "Python" + # salario_base (5000) + bonus(10%) + adicional(500) - desconto(8%) + esperado = 5000 + 500 + 500 - 400 # 5600 + assert desenvolvedor.calcular_salario_liquido() == esperado \ No newline at end of file diff --git a/Guia2/tests/test_estagiario.py b/Guia2/tests/test_estagiario.py new file mode 100644 index 0000000..e1007fe --- /dev/null +++ b/Guia2/tests/test_estagiario.py @@ -0,0 +1,38 @@ +import pytest +from src import Estagiario + + +@pytest.fixture +def estagiario(): + # Salário base 1500, carga horária 30h + return Estagiario("Carlos", "456", 1500.0, "Engenharia", 30) + +# ---- Teste do bônus fixo ---- +def test_bonus_fixo(estagiario): + # 3% do salário base + assert estagiario.calcular_bonus() == 0.03 * estagiario.salario_base + +# ---- Teste do desconto fixo ---- +def test_desconto_fixo(estagiario): + # 2% do salário base + assert estagiario.calcular_descontos() == 0.02 * estagiario.salario_base + +# ---- Testes de adicionais por carga horária ---- +@pytest.mark.parametrize("carga_horaria,adicional_esperado", [ + (20, 150), + (15, 150), # até 20h inclusive + (25, 250), + (30, 250), # até 30h inclusive + (35, 350), + (40, 350), +]) +def test_adicional_por_carga_horaria(estagiario, carga_horaria, adicional_esperado): + estagiario.carga_horaria = carga_horaria + assert estagiario.calcular_adicionais() == adicional_esperado + +# ---- Teste de salário líquido para carga de 30h ---- +def test_salario_liquido_30h(estagiario): + estagiario.carga_horaria = 30 + # 1500 + 45 (bônus) + 250 (adicional) - 30 (desconto) = 1765 + esperado = 1500 + 45 + 250 - 30 + assert estagiario.calcular_salario_liquido() == esperado \ No newline at end of file diff --git a/Guia2/tests/test_gerente.py b/Guia2/tests/test_gerente.py new file mode 100644 index 0000000..da59182 --- /dev/null +++ b/Guia2/tests/test_gerente.py @@ -0,0 +1,47 @@ +import pytest +from src import Gerente + + +@pytest.fixture +def gerente(): + # Salário base 8000, equipe = 5 (para teste básico) + return Gerente("Roberta", "789", 8000.0, "TI", 5) + +# ---- Testes de bônus por tamanho da equipe ---- +@pytest.mark.parametrize("qtd_equipe,percentual_bonus", [ + (3, 0.10), + (5, 0.10), + (6, 0.15), + (10, 0.15), + (11, 0.20), + (20, 0.20), +]) +def test_bonus_por_tamanho_equipe(gerente, qtd_equipe, percentual_bonus): + gerente.qtd_equipe = qtd_equipe + esperado = percentual_bonus * gerente.salario_base + assert gerente.calcular_bonus() == esperado + +# ---- Teste de desconto fixo ---- +def test_desconto_fixo(gerente): + # 12% do salário base + assert gerente.calcular_descontos() == 0.12 * gerente.salario_base + +# ---- Testes de adicional por tamanho da equipe ---- +@pytest.mark.parametrize("qtd_equipe,adicional_esperado", [ + (1, 500), + (5, 500), + (6, 1000), + (10, 1000), + (11, 2000), + (15, 2000), +]) +def test_adicional_por_tamanho_equipe(gerente, qtd_equipe, adicional_esperado): + gerente.qtd_equipe = qtd_equipe + assert gerente.calcular_adicionais() == adicional_esperado + +# ---- Teste integrado para equipe de 8 pessoas ---- +def test_salario_liquido_equipe_8(gerente): + gerente.qtd_equipe = 8 + # bonus 15% = 1200, adicional = 1000, desconto 12% = 960 + esperado = 8000 + 1200 + 1000 - 960 # 9240 + assert gerente.calcular_salario_liquido() == esperado \ No newline at end of file From 6df5bfed13358fca234870bda3636b0689740d4d Mon Sep 17 00:00:00 2001 From: zeguii Date: Sat, 23 May 2026 01:31:07 -0300 Subject: [PATCH 2/2] 22/05 --- Guia1/src/repositories/record_repository.py | 33 ++++++++++++++++----- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/Guia1/src/repositories/record_repository.py b/Guia1/src/repositories/record_repository.py index bded279..ff0e351 100644 --- a/Guia1/src/repositories/record_repository.py +++ b/Guia1/src/repositories/record_repository.py @@ -10,15 +10,34 @@ def __init__(self, file_path: str): def load_all(self): data = FileLoader.load_csv(self._file_path) - self._records = [ - Record(int(row["id"]), row["name"], row["address"]) - for row in data - ] + self._records = [] + + for row in data: + try: + if not row.get("id"): + raise ValueError("ID vazio") + + record_id = int(row["id"]) + + if record_id <= 0: + raise ValueError("ID negativo ou zero") + + if not row.get("name", "").strip() or not row.get("address", "").strip(): + raise ValueError("Nome ou endereço vazio") + + registro = Record(record_id, row["name"], row["address"]) + self._records.append(registro) + + except ValueError: + print(f"Registro inválido ignorado: {row}") + return self._records def search(self, term: str): - term = term.lower() + termos_busca = term.lower().split() + return [ r for r in self._records - if term in r.name.lower() or term in r.address.lower() - ] \ No newline at end of file + if all(t in f"{r.name} {r.address}".lower() for t in termos_busca) + ] + \ No newline at end of file