- Pagsubok sa pagsasama ng isang database gamit ang MariaDB upang palitan ang MySql
- Pagpapatupad ng multilinggwal na aplikasyon
- Pag-save ng mga file sa application at data tungkol sa mga ito sa database
Mga uri ng pagsubok
Ano ang isang pagsubok? Gaya ng sabi ng Wiki: " Ang pagsubok o pagsubok ay isang paraan ng pag-aaral ng mga pinagbabatayan na proseso ng isang system sa pamamagitan ng paglalagay ng system sa iba't ibang sitwasyon at pagsubaybay sa mga nakikitang pagbabago dito." Sa madaling salita, ito ay isang pagsubok ng tamang operasyon ng aming system sa ilang partikular na sitwasyon. Well, tingnan natin kung anong mga uri ng pagsubok ang mayroon:-
Ang unit testing ay mga pagsubok na ang gawain ay subukan ang bawat module ng system nang paisa-isa. Ito ay kanais-nais na ang mga ito ay minimally divisible piraso ng system, halimbawa, modules.
-
Ang system testing ay isang mataas na antas na pagsubok upang subukan ang pagpapatakbo ng isang mas malaking bahagi ng isang application o ng system sa kabuuan.
-
Ang pagsubok ng regression ay pagsubok na ginagamit upang suriin kung ang mga bagong feature o pag-aayos ng bug ay nakakaapekto sa umiiral nang functionality ng application at kung muling lumitaw ang mga lumang bug.
-
Ang functional testing ay ang pagsuri sa pagsunod ng bahagi ng application sa mga kinakailangan na nakasaad sa mga detalye, mga kwento ng user, atbp.
Mga uri ng functional na pagsubok:
- "white box" na pagsubok para sa pagsunod ng bahagi ng aplikasyon sa mga kinakailangan na may kaalaman sa panloob na pagpapatupad ng system;
- "black box" na pagsubok para sa pagsunod ng bahagi ng application sa mga kinakailangan nang walang kaalaman sa panloob na pagpapatupad ng system.
- Ang pagsubok sa pagganap ay isang uri ng mga pagsubok na isinulat upang matukoy ang bilis kung saan tumatakbo ang isang sistema o bahagi nito sa ilalim ng isang tiyak na pagkarga.
- Pagsubok sa pag-load - mga pagsubok na idinisenyo upang suriin ang katatagan ng system sa ilalim ng karaniwang mga pag-load at upang mahanap ang pinakamataas na posibleng peak kung saan gumagana nang tama ang application.
- Ang stress testing ay isang uri ng pagsubok na idinisenyo upang suriin ang functionality ng isang application sa ilalim ng hindi karaniwang mga pag-load at upang matukoy ang pinakamataas na posibleng peak kung saan hindi mag-crash ang system.
- Pagsubok sa seguridad - mga pagsubok na ginagamit upang suriin ang seguridad ng isang system (mula sa mga pag-atake ng mga hacker, mga virus, hindi awtorisadong pag-access sa kumpidensyal na data at iba pang kagalakan ng buhay).
- Ang localization testing ay localization testing para sa isang application.
- Ang usability testing ay isang uri ng pagsubok na naglalayong suriin ang usability, understandability, attractiveness at learnability para sa mga user. Maganda ang lahat ng ito, ngunit paano ito gumagana sa pagsasanay? Simple lang: Ginamit ang testing pyramid ni Mike Cohn: Ito ay isang pinasimpleng bersyon ng pyramid: ngayon ay nahahati ito sa mas maliliit na bahagi. Ngunit ngayon ay hindi namin isasama at isaalang-alang ang pinakasimpleng opsyon.
-
Unit - mga pagsubok sa yunit na ginagamit sa iba't ibang mga layer ng application, pagsubok sa pinakamaliit na divisible logic ng application: halimbawa, isang klase, ngunit kadalasan ay isang paraan. Karaniwang sinusubukan ng mga pagsubok na ito na ihiwalay hangga't maaari mula sa panlabas na lohika, iyon ay, upang lumikha ng ilusyon na ang natitirang bahagi ng application ay gumagana sa karaniwang mode.
Dapat palaging mayroong maraming mga pagsubok na ito (higit pa kaysa sa iba pang mga uri), dahil sinusubok nila ang maliliit na piraso at napakagaan, hindi kumonsumo ng maraming mapagkukunan (sa mga mapagkukunan ang ibig kong sabihin ay RAM at oras).
-
Pagsasama - pagsubok sa pagsasama. Sinusuri nito ang mas malalaking piraso ng system, iyon ay, ito ay alinman sa kumbinasyon ng ilang piraso ng lohika (ilang mga pamamaraan o klase), o ang kawastuhan ng pagtatrabaho sa isang panlabas na bahagi. Karaniwang mas kaunti ang mga pagsubok na ito kaysa sa mga pagsubok sa Unit, dahil mas mabigat ang mga ito.
Bilang isang halimbawa ng mga pagsubok sa pagsasama, maaari mong isaalang-alang ang pagkonekta sa isang database at suriin ang tamang pagpapatupad ng mga pamamaraan na gumagana dito .
-
UI - mga pagsubok na sumusuri sa pagpapatakbo ng user interface. Nakakaapekto ang mga ito sa lohika sa lahat ng antas ng application, kaya naman tinatawag din silang end-to-end. Bilang isang patakaran, marami ang mas kaunti sa kanila, dahil sila ang pinaka-mabigat at dapat suriin ang pinaka-kinakailangang (ginamit) na mga landas.
Sa figure sa itaas nakikita natin ang ratio ng mga lugar ng iba't ibang bahagi ng tatsulok: humigit-kumulang sa parehong proporsyon ay pinananatili sa bilang ng mga pagsubok na ito sa totoong trabaho.
Ngayon ay susuriin natin nang mas malapitan ang mga pinakaginagamit na pagsubok - mga pagsubok sa yunit, dahil lahat ng may paggalang sa sarili na mga developer ng Java ay dapat na magamit ang mga ito sa isang pangunahing antas.
- materyal tungkol sa Code Coverage sa JavaRush at sa Habré ;
- pangunahing teorya ng pagsubok .
- Sinusulat namin ang aming pagsubok.
- Pinapatakbo namin ang pagsubok, pumasa man ito o hindi (nakikita namin na ang lahat ay pula - huwag matakot: ganito dapat).
- Nagdaragdag kami ng code na dapat masiyahan sa pagsubok na ito (patakbuhin ang pagsubok).
- Refactor namin ang code.
- Pagtukoy sa data na susuriin (mga fixture).
- Gamit ang code sa ilalim ng pagsubok (pagtawag sa pamamaraan sa ilalim ng pagsubok).
- Sinusuri ang mga resulta at inihambing ang mga ito sa mga inaasahan.
assertEquals(Object expecteds, Object actuals)
— sinusuri kung ang mga ipinadalang bagay ay pantay.assertTrue(boolean flag)
— sinusuri kung totoo ang naibalik na halaga.assertFalse(boolean flag)
— sinusuri kung ang ipinasa na halaga ay nagbabalik ng false.assertNull(Object object)
– sinusuri kung ang bagay ay null.assertSame(Object firstObject, Object secondObject)
— sinusuri kung ang mga naipasa na halaga ay tumutukoy sa parehong bagay.assertThat(T t, Matcher<T> matcher)
— sinusuri kung t natutugunan ang kundisyong tinukoy sa matcher.
Mga pangunahing konsepto ng pagsubok sa yunit
Ang saklaw ng pagsubok (Code Coverage) ay isa sa mga pangunahing pagtatasa ng kalidad ng pagsubok sa aplikasyon. Ito ang porsyento ng code na sakop ng mga pagsubok (0-100%). Sa pagsasagawa, maraming tao ang humahabol sa porsyentong ito, na hindi ko sinasang-ayunan, dahil nagsimula silang magdagdag ng mga pagsubok kung saan hindi sila kailangan. Halimbawa, ang aming serbisyo ay may karaniwang mga operasyong CRUD (gumawa/kumuha/mag-update/magtanggal) nang walang karagdagang lohika. Ang mga paraang ito ay puro tagapamagitan na nagdedelegate ng trabaho sa layer na gumagana sa repositoryo. Sa sitwasyong ito, wala tayong susubukan: marahil kung ang pamamaraang ito ay tumatawag ng isang pamamaraan mula sa Tao, ngunit hindi ito seryoso. Upang masuri ang saklaw ng pagsubok, ang mga karagdagang tool ay karaniwang ginagamit: JaCoCo, Cobertura, Clover, Emma, etb. Para sa mas detalyadong pag-aaral ng isyung ito, panatilihin ang ilang angkop na artikulo:Mga yugto ng pagsubok
Ang pagsusulit ay binubuo ng tatlong yugto:Mga kapaligiran sa pagsubok
Kaya ngayon, bumaba tayo sa negosyo. Mayroong ilang mga kapaligiran sa pagsubok (mga balangkas) na magagamit para sa Java. Ang pinakasikat sa kanila ay ang JUnit at TestNG. Para sa aming pagsusuri, ginagamit namin ang: Ang JUnit test ay isang paraan na nasa isang klase na ginagamit lamang para sa pagsubok. Ang isang klase ay karaniwang pinangalanang kapareho ng klase na sinusubok nito gamit ang +Test sa dulo. Halimbawa, CarService→ CarServiceTest. Awtomatikong kasama sa Maven build system ang mga ganitong klase sa lugar ng pagsubok. Sa katunayan, ang klase na ito ay tinatawag na klase ng pagsubok. Isaalang-alang natin nang kaunti ang mga pangunahing anotasyon: @Test - kahulugan ng pamamaraang ito bilang isang paraan ng pagsubok (sa katunayan, ang pamamaraang minarkahan ng anotasyong ito ay isang pagsubok sa yunit). @Before - minarkahan ang paraan na isasagawa bago ang bawat pagsubok. Halimbawa, pagpuno ng data ng pagsubok sa klase, pagbabasa ng data ng input, atbp. @After - inilagay sa itaas ng paraan na tatawagin pagkatapos ng bawat pagsubok (paglilinis ng data, pagpapanumbalik ng mga default na halaga). @BeforeClass - inilagay sa itaas ng pamamaraan - kahalintulad sa @Before. Ngunit ang pamamaraang ito ay tinatawag na isang beses lamang bago ang lahat ng mga pagsubok para sa isang partikular na klase at samakatuwid ay dapat na static. Ginagamit ito upang magsagawa ng mas mabibigat na mga operasyon, tulad ng pag-angat ng isang database ng pagsubok. Ang @AfterClass ay kabaligtaran ng @BeforeClass: naisakatuparan nang isang beses para sa isang partikular na klase, ngunit naisakatuparan pagkatapos ng lahat ng pagsubok. Ginagamit, halimbawa, upang linisin ang mga patuloy na mapagkukunan o idiskonekta mula sa database. @Ignore - tandaan na ang pamamaraan sa ibaba ay hindi pinagana at hindi papansinin kapag nagpapatakbo ng mga pagsubok sa pangkalahatan. Ito ay ginagamit sa iba't ibang mga kaso, halimbawa, kung ang base na paraan ay binago at walang oras upang gawing muli ang pagsubok para dito. Sa ganitong mga kaso, ipinapayong magdagdag ng paglalarawan - @Ignore("Some description"). @Test (inaasahan = Exception.class) - ginagamit para sa mga negatibong pagsubok. Ito ay mga pagsubok na nagsusuri kung paano kumikilos ang isang pamamaraan kung sakaling magkaroon ng error, iyon ay, inaasahan ng pagsubok na ang pamamaraan ay maghagis ng ilang pagbubukod. Ang ganitong paraan ay tinutukoy ng @Test annotation, ngunit may error na mahuhuli. @Test(timeout=100) - sinusuri kung ang pamamaraan ay gumagana nang hindi hihigit sa 100 millisecond. @Mock - ang isang klase ay ginagamit sa isang patlang upang itakda ang isang ibinigay na bagay bilang isang mock (ito ay hindi mula sa Junit library, ngunit mula sa Mockito), at kung kailangan natin ito, itatakda natin ang pag-uugali ng mock sa isang partikular na sitwasyon , direkta sa paraan ng pagsubok. @RunWith(MockitoJUnitRunner.class) - ang pamamaraan ay inilalagay sa itaas ng klase. Ito ang pindutan para sa pagpapatakbo ng mga pagsubok dito. Maaaring iba ang mga runner: halimbawa, mayroong mga sumusunod: MockitoJUnitRunner, JUnitPlatform, SpringRunner, atbp.). Sa JUnit 5, ang @RunWith annotation ay pinalitan ng mas malakas na @ExtendWith annotation. Tingnan natin ang ilang mga pamamaraan para sa paghahambing ng mga resulta:assertThat(firstObject).isEqualTo(secondObject)
Dito napag-usapan ko ang tungkol sa mga pangunahing pamamaraan, dahil ang iba ay iba't ibang mga pagkakaiba-iba ng nasa itaas.
Pagsasanay sa pagsubok
Ngayon tingnan natin ang materyal sa itaas gamit ang isang tiyak na halimbawa. Susubukan namin ang paraan para sa serbisyo - pag-update. Hindi namin isasaalang-alang ang dao layer, dahil ito ang aming default. Magdagdag tayo ng starter para sa mga pagsubok:<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.2.2.RELEASE</version>
<scope>test</scope>
</dependency>
Kaya, ang klase ng serbisyo:
@Service
@RequiredArgsConstructor
public class RobotServiceImpl implements RobotService {
private final RobotDAO robotDAO;
@Override
public Robot update(Long id, Robot robot) {
Robot found = robotDAO.findById(id);
return robotDAO.update(Robot.builder()
.id(id)
.name(robot.getName() != null ? robot.getName() : found.getName())
.cpu(robot.getCpu() != null ? robot.getCpu() : found.getCpu())
.producer(robot.getProducer() != null ? robot.getProducer() : found.getProducer())
.build());
}
}
8 - hilahin ang na-update na bagay mula sa database 9-14 - lumikha ng bagay sa pamamagitan ng tagabuo, kung ang papasok na bagay ay may isang patlang - itakda ito, kung hindi - iwanan kung ano ang nasa database At tingnan ang aming pagsubok:
@RunWith(MockitoJUnitRunner.class)
public class RobotServiceImplTest {
@Mock
private RobotDAO robotDAO;
private RobotServiceImpl robotService;
private static Robot testRobot;
@BeforeClass
public static void prepareTestData() {
testRobot = Robot
.builder()
.id(123L)
.name("testRobotMolly")
.cpu("Intel Core i7-9700K")
.producer("China")
.build();
}
@Before
public void init() {
robotService = new RobotServiceImpl(robotDAO);
}
1 — ang aming Runner 4 — ihiwalay ang serbisyo mula sa layer ng dao sa pamamagitan ng pagpapalit ng mock 11 — magtakda ng isang pansubok na entity para sa klase (ang isa na gagamitin namin bilang isang pagsubok na hamster) 22 — magtakda ng isang bagay ng serbisyo na aming susuriin
@Test
public void updateTest() {
when(robotDAO.findById(any(Long.class))).thenReturn(testRobot);
when(robotDAO.update(any(Robot.class))).then(returnsFirstArg());
Robot robotForUpdate = Robot
.builder()
.name("Vally")
.cpu("AMD Ryzen 7 2700X")
.build();
Robot resultRobot = robotService.update(123L, robotForUpdate);
assertNotNull(resultRobot);
assertSame(resultRobot.getId(),testRobot.getId());
assertThat(resultRobot.getName()).isEqualTo(robotForUpdate.getName());
assertTrue(resultRobot.getCpu().equals(robotForUpdate.getCpu()));
assertEquals(resultRobot.getProducer(),testRobot.getProducer());
}
Dito makikita natin ang isang malinaw na dibisyon ng pagsubok sa tatlong bahagi: 3-9 - pagtatakda ng mga fixtures 11 - pagpapatupad ng nasubok na bahagi 13-17 - pagsuri sa mga resulta Higit pang mga detalye: 3-4 - pagtatakda ng gawi para sa moka dao 5 - setting ang instance na ia-update namin sa ibabaw ng aming standard 11 - gamitin ang paraan at kunin ang resultang instance 13 - suriin na ito ay hindi zero 14 - suriin ang resulta ID at ang tinukoy na paraan argumento 15 - suriin kung ang pangalan ay na-update 16 - tingnan ang resulta ng cpu 17 - dahil hindi namin ito itinakda sa patlang ng halimbawa ng pag-update, dapat itong manatiling pareho, suriin natin ito. Ilunsad natin: Ang pagsubok ay berde, maaari kang huminga)) Kaya, sabihin sa buod: ang pagsubok ay nagpapabuti sa kalidad ng code at ginagawang mas nababaluktot at maaasahan ang proseso ng pagbuo. Isipin kung gaano karaming pagsisikap ang kailangan nating gastusin kapag muling nagdidisenyo ng software na may daan-daang mga file ng klase. Kapag mayroon na tayong mga unit test na isinulat para sa lahat ng klaseng ito, maaari tayong mag-refactor nang may kumpiyansa. At ang pinakamahalaga, nakakatulong ito sa amin na madaling makahanap ng mga error sa panahon ng pag-unlad. Guys, iyon lang para sa akin ngayon: ibuhos ang mga gusto, magsulat ng mga komento)))
GO TO FULL VERSION