Кіріспе

Оқшауланған бастапқы кодтың жұмысын растау.

Бөлшектік сынақ, яғни компоненттік немесе модульдік сынақ – бұл бағдарламалық қамтамасыз етуді сынаудың бір түрі, онда оқшауланған бастапқы код күтілетін нәтижелерге сәйкес келе ма екенін анықтау үшін тексеріледі. Бөлшектік сынақ – интеграциялық немесе жүйелік деңгейдегі сынақтардан өзгеше, жеке модульдар деңгейінде жүргізілетін сынақтарды сипаттайды.

Тарих

Бөлшектік тестілеу, ірі бағдарламалық жүйелердің кішігірім бөліктерін жеке-жеке тексеру принципі ретінде, бағдарламалық инженерияның алғашқы күндеріне дейін барады. 1956 жылдың маусым айында Х.Д. Бенингтон АҚШ Әскери-теңіз күштерінің Цифрлық компьютерлерді бағдарламалаудың озық әдістері жөніндегі симпозиумында SAGE жобасын және оның спецификацияға негізделген тәсілін ұсынды, онда кодтау кезеңінен кейін компоненттік бағдарламаларды олардың спецификациясына сәйкес тексеру үшін "параметрлік тестілеу" жүргізілді, содан кейін жиналған бөліктер үшін "жинастыру тестілеуі" орындалды. 1964 жылы Меркурий жобасының бағдарламалық жасақтамасы үшін ұқсас тәсіл сипатталды, онда әртүрлі бағдарламалармен әзірленген жеке бөлімдер біріктірілмес бұрын "бөлімдік тестілеуден" өтті. 1969 жылы тестілеу әдістемелері көбірек құрылымдалған болып көрінеді, бөлімдік тестілеулер, компоненттік тестілеулер және интеграциялық тестілеулер жеке жазылған бөліктерді және олардың үлкен блоктарға кезең-кезеңмен құрастырылуын тексеру мақсатында пайда болды. 60-жылдардың соңында қабылданған MIL STD 483 және MIL STD 490 сияқты бірнеше мемлекеттік стандарттар ірі жобаларда бөлімдік тестілеуді кеңінен қабылдауға көмектесті. Бөлімдік тестілеу сол кезде кодталған тестілерді немесе жазу және қайта ойнату тестілеу құралдарын қолдану арқылы интерактивті түрде жүргізілді. 1989 жылы Кент Бек Smalltalk (кейін SUnit деп аталды) үшін "Жай Smalltalk тестілеуі: Үлгілермен" атты тестілеу аясын сипаттады. 1997 жылы Кент Бек және Эрих Гамма Java бағдарламашылары арасында танымал болған JUnit бөлімдік тестілеу аясын жасап шығарды. Google 2005-2006 жылдар шамасында автоматтандырылған тестілеуді қолдануға көшті.

Бірлік

Бірлік әдетте салыстырмалы түрде аз көлемдегі кодты білдіреді; кодтың қалған бөлігінен бөліп қарастыруға болатын, үлкен және күрделі жүйе болуы мүмкін код. Процедуралық бағдарламалауда бірлік әдетте функция немесе модуль болып табылады. Объектіге бағытталған бағдарламалауда бірлік әдетте әдіс, объект немесе класс болып табылады.

Атқару

Бөлшек сынақтар қолмен немесе автоматтандырылған сынақ орындау арқылы жүзеге асырылуы мүмкін. Автоматтандырылған сынақтардың артықшылықтарына мыналар жатады: сынақтарды жиі орындау, еңбек құны жоқ сынақтарды орындау, тұрақты және қайталанатын сынақтарды жүргізу. Сынақтарды көбінесе сыналып жатқан кодты жазатын және өзгертетін бағдарламашы жүргізеді. Бөлшек сынақтарды код жазу процесінің бір бөлігі деп қарастыруға болады.

Сынау критерийлері

Даму кезінде бағдарламашы бірліктің дұрыстығын тексеру үшін, жақсы деп белгілі критерийлерді немесе нәтижелерді тестке енгізе алады. Тест орындау кезінде, кез келген критерийді орындамаған тесттер тіркелді және олар қорытындыда көрсетіледі. Мұндай жағдайларда, ең көп қолданылатын тәсіл – тест функциясының күтілетін мәнін салыстыру.

Параметрленген сынақ

Параметрленген сынақ – бірнеше әртүрлі кіріс мәндерімен сынақты орындауға мүмкіндік беретін мәндер жиынтығын қабылдайтын сынақ. Параметрленген сынақтарды қолдайтын сынақ фреймворкі параметрлер жиынтығын кодтау және сынақты әрбір жиынтықпен орындау тәсілін ұсынады. Параметрленген сынақтарды пайдалану сынақ кодын қайталауды азайтуға көмектеседі. TestNG, JUnit, XUnit және NUnit, сондай-ақ түрлі JavaScript сынақ фреймворктері параметрленген сынақтарды қолдайды. Блок-сынақтардың параметрлері қолмен берілуі мүмкін, немесе кейбір жағдайларда сынақ фреймворкімен автоматты түрде жасалады. Соңғы жылдары, орындалу барысында жасалатын тест деректерін пайдаланатын, бірақ бірдей қадамдарды орындайтын теориялар тұжырымдамасын қолдана отырып, күштірек (блок-) сынақтарды жазуға қолдау қосылды. Бұл, алдын ала анықталған кіріс жиынтықтарымен бірдей орындалу қадамдарын пайдаланатын дәстүрлі параметрленген сынақтардан өзгеше.

Жеңіл

Кейде, икемді бағдарламалық жасақтаманы әзірлеу кезінде, бірлік тестілеу әр пайдаланушы оқиғасы бойынша жасалады және талаптарды жинау мен әзірлеу аяқталғаннан кейін спринттің соңғы жартысында орындалады. Әдетте, әзірлеушілер немесе әзірлеу тобының басқа мүшелері, мысалы консультанттар, әзірлеушілерге құралда орындау үшін қадам-қадам "тест скрипттерін" жазады. Тест скрипттері әдетте құралдағы нақты дамытылған мүмкіндіктердің тиімді және техникалық жұмысын дәлелдеу үшін жазылады, бұл соңғы пайдаланушы интерфейсі арқылы жүзеге асырылатын толыққанды бизнес-процестерден өзгеше, және мұндай тестілеу әдетте пайдаланушы қабылдау тестілеуі кезінде жүргізіледі. Егер тест скриптін бастаудан соңына дейін ешқандай мәселесіз орындау мүмкін болса, бірлік тестілеу "сәтті аяқталған" деп есептеледі, әйтпесе қателер тіркеледі және пайдаланушы оқиғасы "жұмыста" күйіне қайтарылады. Бірлік тестілеуден сәтті өткен пайдаланушы оқиғалары спринттің соңғы қадамдарына – кодты қарауға, әріптестердің пікірлеріне, содан кейін әзірленген құралды мүдделі тараптарға көрсету сессиясына ("демонстрация") көшіріледі.

Сынақпен жүргізілетін даму

Сынақпен басқарылатын әзірлеуде (TDD) бірлік тесттері өндірістік код жазылатын кезде жазылады. Жұмыс істейтін кодтан бастап, дамытушы қажетті мінез-құлық үшін тест кодын қосады, содан кейін тек тестің өтуі үшін жеткілікті кодты ғана қосады, содан кейін кодты (тест кодын қоса алғанда) орынды жағдайда жаңартады және осы процесті тағы бір тест қосу арқылы қайталайды.

Құны

Бөлшектік сынақтардың мақсаты – кодтың бөліктері жобаланғандай жұмыс ілеуін және күтілгендей әрекет ететінін қамтамасыз ету. Ең кішкентай сынаққа тартылатын бөліктерге арналған сынақтарды бірінші болып жазып, содан кейін олардың өзара әрекеттесуін тексеру арқылы күрделі бағдарламалар үшін толыққанды сынақ жүйесін құруға болады. Жаман жазылған кодты бөлшектік сынақтан өткізу мүмкін болмайды немесе қиынға соғуы мүмкін, сондықтан бөлшектік сынақтар бағдарламашыларды функциялар мен объектілерді дұрыс құрылымдауға итермелейді.

Жиірек шығарылатын материалдар

Бөлімдік сынақ бағдарламалық жасақтаманы дамытуда жиірек жаңартулар жасауға мүмкіндік береді. Жеке компоненттерді оқшау тексеру арқылы бағдарламашылар мәселелерді жылдам анықтап, түзетуге болады, бұл тез қайталау және жаңарту циклдарына әкеледі.

Кодты қайта құруға мүмкіндік береді

Бөлшектік тестілеу бағдарламашыға кодты өзгертуге немесе жүйелік кітапханаларды кейін жаңартуға мүмкіндік береді, сондай-ақ модульдің бұрынғысындей дұрыс жұмыс істейтініне көз жеткізуге болады (мысалы, регрессиялық тестілеу кезінде). Мұнда барлық функциялар мен әдістерге арналған тест жағдайларын жазу қажет, осылайша кез келген өзгеріс қате тудырса, оны жылдам анықтауға болады.

Жобалау келісім-шартын бұзуы мүмкін өзгерістерді анықтайды

Бөлшек сынақтары жобалық келісімді бұзуға әкелетін өзгерістерді анықтайды.

Күтпеушілікті азайту

Бөлшектік сынау өз бөліктеріндегі белгісіздікті азайтуға көмектеседі және төменнен жоғарыға қарай сынау әдісін қолдануға мүмкіндік береді. Бағдарламаның бөліктерін бірінші кезекте сынап, содан кейін олардың жиынтығын сынау арқылы интеграциялық сынақтарды жүргізу әлдеқайда жеңілдеді.

Жүйелік мінез-құлықты құжаттау

Кейбір бағдарламашылар бірлік тесттері кодтың бір түріндегі құжаттама болып табылады деп санайды. Бірлік қандай функционалдылықты ұсынатынын және оны қалай пайдалануға болатынын білгісі келетін әзірлеушілер, оны түсіну үшін бірлік тесттерін қарастыра алады. Тест жағдайлары бірліктің сәтті болуы үшін маңызды ерекшеліктерді қамти алады. Бұл ерекшеліктер бірліктің дұрыс немесе қате пайдаланылуын, сондай-ақ бірлік тоқтатуға тиіс жағымсыз әрекеттерді көрсетуі мүмкін. Тест жағдайы осы маңызды ерекшеліктерді құжаттайды, бірақ көптеген бағдарламалық жасақтаманы әзірлеу орталары өнімді құжаттау үшін тек кодқа ғана сүйенбейді. Кейбір процестерде тесттерді жазу және тексерілетін код, сондай-ақ оған байланысты қайта құру формальды жобалаудың орнын басады. Әрбір бірлік тестісі сыныптарды, әдістерді және байқалатын мінез-құлықты анықтайтын жобалау элементі ретінде қарастырылуы мүмкін.

Шектеулері мен кемшіліктері

Сынау бағдарламадағы барлық қателерді анықтай алмайды, өйткені ең қарапайым бағдарламалардан басқа кез келген орындалу жолын бағалай алмайды. Бұл мәселе тоқтату мәселесінің кеңейтілген түрі болып табылады, ол шешілмейтін мәселе. Бұл бірліктерді сынауға да қатысты. Бірліктерді сынау, анықтамасы бойынша, тек жеке бірліктердің функционалдығын тексереді. Сондықтан ол интеграциялық қателерді немесе жүйелік деңгейдегі кеңірек қателерді (мысалы, бірнеше бірліктерде орындалатын функциялар немесе өнімділік сияқты функционалдық емес сынақ салалары) анықтай алмайды. Бірліктерді сынау, басқа бағдарламалық жасақтаманы сынау әрекеттерімен бірге жүргізілуі керек, өйткені олар тек белгілі бір қателердің бар-жоғын ғана көрсете алады, бірақ қателердің толық жоқтығын дәлелдей алмайды. Әрбір орындалу жолы мен барлық мүмкін кіріс үшін дұрыс жұмыс ілеуін кепілдіру және қателердің жоқтығын қамтамасыз ету үшін басқа әдістер қажет, атап айтқанда, бағдарламалық жасақтама компонентінің күтпеген әрекеттері жоқ екенін дәлелдеу үшін формалды әдістерді қолдану. Бірліктерді сынаудың күрделі иерархиясы интеграциялық сынаумен тең емес. Перифериялық бірліктермен интеграция интеграциялық сынауға енгізілуі керек, бірақ бірліктерді сынауға емес. Интеграциялық сынау әдетте қолмен сынауға көп сүйенеді, өйткені жоғары деңгейдегі немесе кең ауқымды сынауды автоматтандыру қиын болуы мүмкін, сондықтан қолмен сынау көбінесе жылдам және арзан болып көрінеді. Бағдарламалық жасақтаманы сынау – комбинаторлық мәселе. Мысалы, кез келген логикалық шешімді мәлімдеме кем дегенде екі сынақ талап етеді: біреуі "ақиқат" нәтижесімен және біреуі "жалған" нәтижесімен. Нәтижесінде, жазылған әрбір код жолы үшін бағдарламашыларға көбінесе 3-тен 5-ке дейін сынақ кодын жазу қажет болады. Бұл уақытты қажет етеді және бұл үшін жұмсалған күш-жігер ақталмауы мүмкін. Сондай-ақ, сынау қиын немесе мүмкін емес мәселелер де бар, мысалы, детерминистік емес немесе бірнеше жіптерді қамтитын мәселелер. Сонымен қатар, бірліктерді сынау үшін жазылған код, сыналатын код сияқты, қате болуы мүмкін. Фред Брукс "Мифтік адам-ай" еңбегінде былай дейді: "Ешқашан екі хронометрмен теңізге шығушы болмаңыз, біреуін немесе үшеуін алыңыз". Яғни, егер екі хронометр бір-біріне қайшы келсе, қайсысы дұрыс екенін қалай білуге болады?

Реалистік және пайдалы сынақтарды ұйымдастыру қиындықтары

Бөлшек тесттерді жазудағы тағы бір қиындық – шынайы және пайдалы тесттерді дайындаудың қиындығы. Тестіленіп жатқан қолданба бөлігі, толық жүйенің бір бөлігі сияқты жұмыс істеуі үшін маңызды бастапқы шарттарды жасау қажет. Егер осы бастапқы шарттар дұрыс орнатылмаса, тест кодты шынайы контекстте сынамайды, бұл бөлшек тесттердің нәтижелерінің құндылығы мен дәлдігін азайтады.

Даму процесінде тәртіпті талап етеді

Бөлшек тестілеуден күтілетін нәтижелерді алу үшін, бағдарламалық құралды әзірлеу процесінің барлық кезеңінде қатаң ұстаным қажет.

Версияны бақылау қажет

Тек орындалған сынақтардың ғана емес, сонымен қатар осы немесе бағдарламалық қамтамасының кез келген басқа бөлігінің бастапқы кодына енгізілген барлық өзгерістердің мұқият тіркемелерін сақтау қажет. Версияны басқару жүйесін пайдалану міндетті. Егер бөлімнің кейінгі нұсқасы бұрын сәтті өткен белгілі бір сынақтан өтпесе, версияны басқару бағдарламалық жасақтамасы сол уақыттан бері бөлімге енгізілген бастапқы кодтың өзгерістерінің тізімін (бар болса) ұсына алады.

Тұрақты тексеруді қажет етеді

Сондай-ақ, сынақтардағы қателердің үнемі қаралып, дереу түзетілуін қамтамасыз ететін тұрақты процесті енгізу өте қажет. Егер мұндай процесс құрылмаса және команданың жұмыс процесіне сіңірілмесе, қолданба бірлік тесттері жинағымен үйлесімсіз дамиды, бұл жалған оң нәтижелердің көбеюіне және тест жинағының тиімділігінің төмендеуіне әкеледі.

Енгізілген жүйелік бағдарламалық қамтамасыз етудің шектеулері

Кіріктірілген жүйелік бағдарламалық жасақтаманы модульдік түрде сынау ерекше қиындық тудырады: Бағдарламалық жасақтама соңымен жұмыс істейтін ортадан өзге платформада жасалғандықтан, десктоптық бағдарламалардағыдай, тесттік бағдарламаны тікелей қолданыс ортасында іске қосу мүмкін болмайды.

Сыртқы жүйелермен интеграцияны сынаудың шектеулері

Бірлік тесттері әдіс кіріс параметрлері мен белгілі бір нәтиже берген кезде жасауға ең оңай болады. Әдістің басты қызметі қолданбаның сыртындағы бір нәрсемен байланысқа түсу болса, бірлік тесттерін жасау қиынға түседі. Мысалы, дерекқормен жұмыс істейтін әдіс үшін дерекқормен байланысқандағы макет жасалуы керек, ол нақты дерекқормен байланысқандай толық болмауы мүмкін.

Орындалатын ерекшеліктер ретінде

Бөлшек сынақтарды жобалау сипаттамасы ретінде пайдаланудың басқа жобалау әдістеріне қарағанда бір маңызды артықшылығы бар: жобалау құжаты (бірлік сынақтардың өзі) іске асыруды тексеру үшін қолданылуы мүмкін. Егер дамытушы жобаға сәйкес шешімді іске асырмаса, сынақтар ешқашан өте алмайды. Бөлшек сынақта UML диаграммасы сияқты графикалық сипаттамалардың жеңілдігі жетіспейді, бірақ оларды бірлік сынақтардан автоматтандырылған құралдар арқылы жасауға болады. Көптеген қазіргі тілдерде тегін құралдар бар (әдетте IDE кеңейтімдері ретінде қол жетімді). xUnit фреймворкіне негізделген тегін құралдар, адамдарға көріну үшін графикалық түрде көрсетуді басқа жүйеге жүктейді.

Экстремалды бағдарламалау

Бөлшек тестілеу – автоматтандырылған бірлік тестілеу құралына негізделген экстремалды бағдарламалаудың тірегі. Бұл автоматтандырылған бірлік тестілеу құралын үшінші тараптан, мысалы, xUnit-тен алуға немесе әзірлеу тобының өзі жасауына болады. Экстремалды бағдарламалау, сынақпен басқарылатын даму үшін бірлік тесттерін жасауды пайдаланады. Бағдарламашы бағдарламалық қамтамасыз ету талабын немесе кемшілікті ашып көрсететін бірлік тестін жазады. Бұл тест сәтсіз аяқталады, өйткені талап әлі іске асырылмаған немесе ол қолданыстағы кодтағы кемшілікті әдейілей көрсетеді. Содан кейін бағдарламашы, тестті және басқа тесттерді сәтті өту үшін ең қарапайым кодты жазады. Жүйедегі кодтың көп бөлігі бірлікпен тестіленеді, бірақ кодтағы барлық жолдар міндетті түрде тексерілмейді. Экстремалды бағдарламалау дәстүрлі "әрбір орындалу жолын тестілеу" әдісіне қарағанда "бұзылуы мүмкін барлық нәрсені тестілеу" стратегиясын қолдайды. Бұл бағдарламашыларды классикалық әдістерге қарағанда аз тесттер жасауға итермелейді, бірақ бұл мәселе емес, жай ғана фактінің қайталануы, өйткені классикалық әдістер барлық орындалу жолдарын жеткілікті түрде тексеру үшін әдетте жүзеге асырылмайды. Экстремалды бағдарламалау тестілеудің сирек толық болатынын (өйткені ол көбінесе тым қымбат және экономикалық тұрғыдан тиімді болу үшін көп уақыт алады) мойындайды және шектеулі ресурстарды тиімді бағыттау бойынша ұсынымдар береді. Ең маңыздысы, тест коды – жобаның бірінші дәрежелі артефактісі саналады, ол барлық қайталаулар алынып тасталған, іске асыру кодымен бірдей сапада сақталады. Бағдарламашылар бірлік тестілеу кодын, оны тестілейтін кодпен бірге код репозиторийіне жібереді. Экстремалды бағдарламалаудың мұқият бірлік тестілеуі жоғарыда аталған артықшылықтарға мүмкіндік береді, мысалы, қарапайым және сенімді кодты әзірлеу және қайта құру, кодты интеграциялауды жеңілдету, дәл құжаттама және модульдік дизайн. Бұл бірлік тесттері сонымен қатар регрессиялық тестілеудің бір түрі ретінде үнемі жүргізіледі. Бөлшек тестілеу Emergent Design тұжырымдамасы үшін де өте маңызды. Жаңадан пайда болатын дизайн рефакторингке көп тәуелді болғандықтан, бірлік тесттері оның ажырамас бөлігі болып табылады.

Автоматтандырылған сынақ жүйелері

Автоматтандырылған тестілеу фреймворкі тестті орындауды автоматтандыру мүмкіндіктерін ұсынады және тесттерді жазу мен орындауды үдетуге көмектеседі. Әртүрлі бағдарламалау тілдері үшін фреймворктер әзірленген. Әдетте, фреймворктер үшінші тараптан шығарылады; олар компилятормен немесе интеграцияланған даму ортасымен (IDE) бірге таралмайды. Тесттерді фреймворк қолданбай-ақ жазуға болады, сынақтан өтетін кодты тексеру үшін асерцияларды, қателерді басқаруды және мінез-құлқыны растау үшін басқа да басқару ағыны механизмдерін пайдаланып, сәтсіздік туралы хабарлауға болады. Кейбір мамандар фреймворксіз тестілеудің пайдалы екенін айтады, себебі фреймворкке көшуге кедергілер бар; қандай да бір тесттің болмауынан жақсы, бірақ фреймворк орнатылғаннан кейін тесттерді қосу оңайырақ болуы мүмкін. Кейбір фреймворктерде кеңейтілген тест мүмкіндіктері жетіспейді және оларды қолмен кодтау қажет.