JavaRush /Java blogi /Random-UZ /Keling, bot bilan ishlash uchun buyruq naqshini amalga os...

Keling, bot bilan ishlash uchun buyruq naqshini amalga oshiramiz. (2-qism) - "A dan Zgacha Java loyihasi"

Guruhda nashr etilgan

Biz dastur uchun testlar yozamiz

Maqolaning boshlanishi: JRTB-3 yozish . Endi biz sinov haqida o'ylashimiz kerak. Funktsionallik biz kutgandek ishlashiga ishonch hosil qilishimiz uchun barcha qo'shilgan kodlar testlar bilan qoplanishi kerak. Avval biz SendBotMessageService xizmati uchun birlik testlarini yozamiz.
Birlik testi - bu dasturning kichik bir qismining mantiqini sinab ko'radigan test: odatda bu usullar. Va bu usulga ega bo'lgan barcha ulanishlar masxara yordamida soxta narsalar bilan almashtiriladi.
Endi siz hamma narsani ko'rasiz. Xuddi shu paketda, faqat ./src/test/java papkasida biz sinab ko'radigan sinf bilan bir xil nomdagi sinf yaratamiz va oxirida Test ni qo'shamiz . Ya'ni, SendBotMessageService uchun bizda SendBotMessageServiceTest bo'ladi , bu sinf uchun barcha testlarni o'z ichiga oladi. Uni sinovdan o'tkazish g'oyasi quyidagicha: biz soxta (soxta) JavaRushTelegarmBot-ga o'tamiz, undan so'ng biz bajarish usuli shunday dalil bilan chaqirilganmi yoki yo'qmi, deb so'raymiz. Mana nima bo'ldi:
package com.github.javarushcommunity.jrtb.service;

import com.github.javarushcommunity.jrtb.bot.JavarushTelegramBot;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;

@DisplayName("Unit-level testing for SendBotMessageService")
public class SendBotMessageServiceTest {

   private SendBotMessageService sendBotMessageService;
   private JavarushTelegramBot javarushBot;

   @BeforeEach
   public void init() {
       javarushBot = Mockito.mock(JavarushTelegramBot.class);
       sendBotMessageService = new SendBotMessageServiceImpl(javarushBot);
   }

   @Test
   public void shouldProperlySendMessage() throws TelegramApiException {
       //given
       String chatId = "test_chat_id";
       String message = "test_message";

       SendMessage sendMessage = new SendMessage();
       sendMessage.setText(message);
       sendMessage.setChatId(chatId);
       sendMessage.enableHtml(true);

       //when
       sendBotMessageService.sendMessage(chatId, message);

       //then
       Mockito.verify(javarushBot).execute(sendMessage);
   }
}
Mockito-dan foydalanib, men soxta JavaRushBot ob'ektini yaratdim va uni xizmatimiz konstruktoriga topshirdim. Keyin men bitta test yozdim (Test izohi bilan har bir usul alohida test). Ushbu usulning tuzilishi har doim bir xil - u hech qanday dalil talab qilmaydi va bekor qiladi. Sinov nomi biz nimani sinab ko'rayotganimizni ko'rsatishi kerak. Bizning holatda, bu: xabarni to'g'ri yuborish kerak - xabarni to'g'ri yuborish kerak. Bizning testimiz uch qismga bo'lingan:
  • blok //berilgan - bu erda biz test uchun zarur bo'lgan hamma narsani tayyorlaymiz;
  • blok //qachon - biz sinab ko'rishni rejalashtirgan usulni ishga tushiradigan joy;
  • //keyin blok - bu erda usul to'g'ri ishlaganligini tekshiramiz.
Bizning xizmatimizdagi mantiq hozircha oddiy bo'lgani uchun, bu sinf uchun bitta test etarli bo'ladi. Endi CommandContainer uchun test yozamiz:
package com.github.javarushcommunity.jrtb.command;

import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import java.util.Arrays;

@DisplayName("Unit-level testing for CommandContainer")
class CommandContainerTest {

   private CommandContainer commandContainer;

   @BeforeEach
   public void init() {
       SendBotMessageService sendBotMessageService = Mockito.mock(SendBotMessageService.class);
       commandContainer = new CommandContainer(sendBotMessageService);
   }

   @Test
   public void shouldGetAllTheExistingCommands() {
       //when-then
       Arrays.stream(CommandName.values())
               .forEach(commandName -> {
                   Command command = commandContainer.retrieveCommand(commandName.getCommandName());
                   Assertions.assertNotEquals(UnknownCommand.class, command.getClass());
               });
   }

   @Test
   public void shouldReturnUnknownCommand() {
       //given
       String unknownCommand = "/fgjhdfgdfg";

       //when
       Command command = commandContainer.retrieveCommand(unknownCommand);

       //then
       Assertions.assertEquals(UnknownCommand.class, command.getClass());
   }
}
Bu juda aniq sinov emas. Bu konteynerning mantig'iga tayanadi. Bot qo'llab-quvvatlaydigan barcha buyruqlar Buyruqning nomi ro'yxatida va konteynerda bo'lishi kerak. Shunday qilib, men barcha CommandName o'zgaruvchilarini oldim, Stream API-ga o'tdim va har biri uchun konteynerdan buyruq qidirdim. Agar bunday buyruq bo'lmasa, Noma'lum buyruq qaytariladi. Biz ushbu qatorda tekshiramiz:
Assertions.assertNotEquals(UnknownCommand.class, command.getClass());
UnknownCommand standart bo'lishini tekshirish uchun sizga alohida test kerak - shouldReturnUnknownCommand . Men sizga ushbu testlarni qayta yozishni va tahlil qilishni maslahat beraman. Hozircha jamoalar uchun yarim rasmiy testlar bo'ladi, ammo ular yozilishi kerak. Mantiq SendBotMessageService-ni sinab ko'rish bilan bir xil bo'ladi, shuning uchun men umumiy test mantig'ini AbstractCommandTest sinfiga o'tkazaman va har bir maxsus test klassi meros qilib olinadi va unga kerakli maydonlarni belgilaydi. Barcha testlar bir xil bo'lgani uchun, har safar bir xil narsani yozish oson emas, bundan tashqari, bu yaxshi kod belgisi emas. Umumlashtirilgan mavhum sinf shunday chiqdi:
package com.github.javarushcommunity.jrtb.command;

import com.github.javarushcommunity.jrtb.bot.JavarushTelegramBot;
import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import com.github.javarushcommunity.jrtb.service.SendBotMessageServiceImpl;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.mockito.internal.verification.VerificationModeFactory;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;

/**
* Abstract class for testing {@link Command}s.
*/
abstract class AbstractCommandTest {

   protected JavarushTelegramBot javarushBot = Mockito.mock(JavarushTelegramBot.class);
   protected SendBotMessageService sendBotMessageService = new SendBotMessageServiceImpl(javarushBot);

   abstract String getCommandName();

   abstract String getCommandMessage();

   abstract Command getCommand();

   @Test
   public void shouldProperlyExecuteCommand() throws TelegramApiException {
       //given
       Long chatId = 1234567824356L;

       Update update = new Update();
       Message message = Mockito.mock(Message.class);
       Mockito.when(message.getChatId()).thenReturn(chatId);
       Mockito.when(message.getText()).thenReturn(getCommandName());
       update.setMessage(message);

       SendMessage sendMessage = new SendMessage();
       sendMessage.setChatId(chatId.toString());
       sendMessage.setText(getCommandMessage());
       sendMessage.enableHtml(true);

       //when
       getCommand().execute(update);

       //then
       Mockito.verify(javarushBot).execute(sendMessage);
   }
}
Ko'rib turganingizdek, bizda uchta mavhum usul mavjud, qaysi buyruqni aniqlagandan so'ng, bu erda yozilgan testni bajarishi va to'g'ri bajarilishi kerak. Bu shunday qulay yondashuv, agar asosiy mantiq mavhum sinfda bo'lsa, lekin tafsilotlar avlodlarda aniqlangan. Va bu erda, aslida, maxsus testlarni amalga oshirish:

HelpCommandTest:

package com.github.javarushcommunity.jrtb.command;

import org.junit.jupiter.api.DisplayName;

import static com.github.javarushcommunity.jrtb.command.CommandName.HELP;
import static com.github.javarushcommunity.jrtb.command.HelpCommand.HELP_MESSAGE;

@DisplayName("Unit-level testing for HelpCommand")
public class HelpCommandTest extends AbstractCommandTest {

   @Override
   String getCommandName() {
       return HELP.getCommandName();
   }

   @Override
   String getCommandMessage() {
       return HELP_MESSAGE;
   }

   @Override
   Command getCommand() {
       return new HelpCommand(sendBotMessageService);
   }
}

NoCommandTest:

package com.github.javarushcommunity.jrtb.command;

import org.junit.jupiter.api.DisplayName;

import static com.github.javarushcommunity.jrtb.command.CommandName.NO;
import static com.github.javarushcommunity.jrtb.command.NoCommand.NO_MESSAGE;

@DisplayName("Unit-level testing for NoCommand")
public class NoCommandTest extends AbstractCommandTest {

   @Override
   String getCommandName() {
       return NO.getCommandName();
   }

   @Override
   String getCommandMessage() {
       return NO_MESSAGE;
   }

   @Override
   Command getCommand() {
       return new NoCommand(sendBotMessageService);
   }
}

StartCommandTest:

package com.github.javarushcommunity.jrtb.command;

import org.junit.jupiter.api.DisplayName;

import static com.github.javarushcommunity.jrtb.command.CommandName.START;
import static com.github.javarushcommunity.jrtb.command.StartCommand.START_MESSAGE;

@DisplayName("Unit-level testing for StartCommand")
class StartCommandTest extends AbstractCommandTest {

   @Override
   String getCommandName() {
       return START.getCommandName();
   }

   @Override
   String getCommandMessage() {
       return START_MESSAGE;
   }

   @Override
   Command getCommand() {
       return new StartCommand(sendBotMessageService);
   }
}

StopCommandTest:

package com.github.javarushcommunity.jrtb.command;

import org.junit.jupiter.api.DisplayName;

import static com.github.javarushcommunity.jrtb.command.CommandName.STOP;
import static com.github.javarushcommunity.jrtb.command.StopCommand.STOP_MESSAGE;

@DisplayName("Unit-level testing for StopCommand")
public class StopCommandTest extends AbstractCommandTest {

   @Override
   String getCommandName() {
       return STOP.getCommandName();
   }

   @Override
   String getCommandMessage() {
       return STOP_MESSAGE;
   }

   @Override
   Command getCommand() {
       return new StopCommand(sendBotMessageService);
   }
}

UnknownCommandTest:

package com.github.javarushcommunity.jrtb.command;

import org.junit.jupiter.api.DisplayName;

import static com.github.javarushcommunity.jrtb.command.UnknownCommand.UNKNOWN_MESSAGE;

@DisplayName("Unit-level testing for UnknownCommand")
public class UnknownCommandTest extends AbstractCommandTest {

   @Override
   String getCommandName() {
       return "/fdgdfgdfgdbd";
   }

   @Override
   String getCommandMessage() {
       return UNKNOWN_MESSAGE;
   }

   @Override
   Command getCommand() {
       return new UnknownCommand(sendBotMessageService);
   }
}
O'yin shamga arzigulik ekanligi aniq va AbstractCommandTest tufayli biz yozish oson va tushunarli bo'lgan oddiy va tushunarli testlar bilan yakunlandik. Bundan tashqari, biz kodni keraksiz takrorlashdan xalos bo'ldik (DRY-ga salom -> O'zingizni takrorlamang). Bundan tashqari, endi bizda haqiqiy sinovlar mavjud bo'lib, ular yordamida dasturning ishlashini baholay olamiz. Botning o'zi uchun test yozish ham yaxshi bo'lardi, lekin hamma narsa osonlikcha ishlamaydi va umuman olganda, o'yin, ular aytganidek, shamga loyiq emas. Shuning uchun, bu bosqichda biz o'z vazifamizni bajaramiz. Oxirgi va sevimli narsa - biz majburiyat yaratamiz, deb yozadi xabar: JRTB-3: Telegram Bot buyruqlarini boshqarish uchun qo'shilgan buyruq namunasi Va odatdagidek - Github allaqachon biladi va tortish so'rovini yaratishni taklif qiladi: "A dan Zgacha Java loyihasi": bot bilan ishlash uchun buyruq naqshini amalga oshirish.  2-1-qismQurilish o'tdi va siz allaqachon qila olasiz. birlash... Lekin yo'q! Loyiha versiyasini yangilashni va uni RELEASE_NOTES da yozishni unutibman. Biz yangi versiya bilan yozuvni qo'shamiz - 0.2.0-SNAPSHOT: "A dan Zgacha Java loyihasi": bot bilan ishlash uchun buyruq naqshini amalga oshirish.  2-2 qismBiz ushbu versiyani pom.xml da yangilaymiz va yangi majburiyat yaratamiz: Yangi topshiriq "A dan Zgacha Java loyihasi": bot bilan ishlash uchun buyruq naqshini amalga oshirish.  2-3 qism: JRTB-3: yangilangan RELEASE_NOTES.md"A dan Zgacha Java loyihasi": bot bilan ishlash uchun buyruq naqshini amalga oshirish.  2-4 qism Endi bosing va qurish tugashini kuting. Qurilish o'tdi, siz uni birlashtira olasiz: "A dan Zgacha Java loyihasi": bot bilan ishlash uchun buyruq naqshini amalga oshirish.  2-5 qismmen filialni o'chirmayapman, shuning uchun siz har doim nima o'zgarganini ko'rishingiz va solishtirishingiz mumkin. Bizning vazifalar paneli yangilandi:"A dan Zgacha Java loyihasi": bot bilan ishlash uchun buyruq naqshini amalga oshirish.  2-6 qism

xulosalar

Bugun biz katta ish qildik: ish uchun buyruq shablonini taqdim etdik. Hamma narsa sozlangan va endi yangi jamoani qo'shish oddiy va tushunarli jarayon bo'ladi. Bugun test haqida ham gaplashdik. Biz hatto jamoalar uchun turli testlarda kodni takrorlamaslik bilan biroz o'ynadik. Odatdagidek, men GitHub-da ro'yxatdan o'tishni va ushbu seriyani va u erda ishlayotgan boshqa loyihalarni kuzatish uchun o'z hisobimni kuzatishni taklif qilaman. Men telegram kanalini ham yaratdim , unda yangi maqolalar chiqarilishini takrorlayman. Qizig'i shundaki, kod odatda maqolaning o'zidan bir hafta oldin chiqariladi va men har safar yangi vazifa bajarilganda yozaman, bu menga maqolani o'qishdan oldin kodni aniqlash imkoniyatini beradi. Tez orada men botni doimiy ravishda nashr etaman va telegram kanaliga obuna bo'lganlar bu haqda birinchilardan bo'lib xabardor bo'lishadi ;) O'qiganingiz uchun barchangizga rahmat, davomi.

Seriyadagi barcha materiallar ro'yxati ushbu maqolaning boshida.

Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION