;

Testujete svůj software důkladně?

10. 1. 2014
Doba čtení: 4 minuty

Sdílet

Autor: © pressmaster - Fotolia.com
Rozličné fáze testování softwaru jsou komplexní a velmi širokou oblastí. Proto jsme se rozhodli pokusit se vše zjednodušit a celou fázi kontroly kvality vyvíjeného softwaru rozdělit do tří nejdůležitějších kategorií. Pokud sami vyvíjíte software, můžete si ověřit, jestli při testování na něco nezapomínáte.

Testy jsou nedílnou a velmi důležitou součástí vývoje softwaru (nebo by tomu tak alespoň být mělo). Problém je, že testy mohou být velmi obšírné a testovací fáze může zahrnovat celou řadu různých typů zkoušek. A že se někdy namísto slůvka testování používají pojmy jako verifikace či validace, jen potvrzuje, o jak širokou oblast se jedná. Abychom však lépe pochopili celou oblast testování, můžeme jí v rámci zjednodušení rozdělit do tří hlavních kategorií:

Technické testy

U testů z této kategorie je důraz kladen především na technickou stránku softwaru. Testeři se nevěnují tomu, zda je program uživatelsky přívětivý nebo jestli se na trhu uchytí. Zajímají se například o to, aby byl zdrojový kód dobře napsaný, aby program fungoval a aby byl kompatibilní s dalším softwarem. Mezi technické testy patří kupříkladu:

Regresní testy: Využívají se při opětovném testování funkcí a vlastností aplikace po zanesení určitých změn (opravené chyby, implementace nových funkcí, vydání nové verze softwaru apod.). Cílem je ověřit, že tyto změny nemají žádný vliv na stávající funkce a vlastnosti. Ověřují se tedy primárně části kódu, které zůstaly beze změn.

Testování kompatibility: Ověření toho, že například řadiče softwaru běží pod určitým operačním systémem/na určitém hardwaru nebo že je software zpětně kompatibilní se starší verzí.

Testování funkcionality (funkční testy): Zkouška toho, zda jednotlivé funkce softwaru fungují dle předpokladů a program plní to, k čemu byl určen (dle zadaných požadavků). Do této kategorie řadíme také testy, které se snaží program „shodit“, bezpečnostní testy, testy instalace atd.

Testy výkonu

Výkonnostní testy bychom sice mohli zařadit do kolonky technických testů, jsou však natolik specifické, že jim věnujeme vlastní kategorii. Fokus zde spočívá na ověření výkonu během různých situací. Mezi testy výkonu patří kupříkladu:

Zátěžové testy: Zkouška škálovatelnosti – co se stane, pokud se např. zvýší počet aktivních uživatelů softwaru? (Pozn.: podle některých metodik jsou zátěžové testy synonymem výkonnostních testů, podle jiných je pouze jedním z typů výkonnostních testů – tak je tomu i v našem rozdělení.)

Test objemu dat: Co se stane, pokud např. databáze „nabobtná“, co do objemu? To ověříte pomocí této zkoušky.

Test hraniční zátěže: Jak software zvládne extrémní zatížení, se dozvíme díky tomuto typu testu.

Testy použitelnosti a UX (user experience)

Cílem těchto testů je ověřit, jak dobře se software obsluhuje, jaká je jeho kvalita, případně jakou má šanci na dnešním trhu. U těchto testů hraje často menší či větší roli osobní vkus testerů, ve finále jde přitom především o to schválit či zavrhnout (navrhnout potřebné úpravy) software, který má být dodán zákazníkovi nebo uveden na trh. Mezi tyto typy testů patří kupříkladu:

Akceptační testy: Odpovídá software specifikacím, je dostačující? V ideálním případě je odpovědí na otázku prosté ano. V reálu však mnohdy uslyšíte něco ve stylu „Software není špatný, je však třeba opravit to či ono…“.

Test použitelnosti: Používá se program snadno? Je uživatelské rozhraní intuitivní? Na tyto a další otázky vám odpoví právě test použitelnosti.

Alfatesty a betatesty: Testování ranné provozuschopné verze softwaru, které se často provádí interně přímo u vývojáře. Podle připomínek se opraví nejzávažnější chyby a následuje betatest, jež už zahrnuje větší počet testerů (často bývá veřejný, např. u počítačových her) a nabízí v podstatě pre-final verzi programu.

Testy lokalizace: Jsou překlady do dalších jazyků v uživatelském rozhraní daného softwaru přesné? Byl program přizpůsoben také reáliím každého státu (např. správná měna)?

Další testy

Zvláštní kategorie testů se zabývá kontrolou toho, jak probíhal samotný vývoj softwaru. Ta většinou zahrnuje kontrolu rizik, potřebného času a nákladů za pomoci různých metrik. O tom však někdy příště…

Čtěte také:

→ HP Unified Functional Testing pomůže s testováním funkčnosti softwaru

Cyber25

→ Agilní a extrémní programování: Úvod do problematiky aneb kde se vzala formalizovaná revize kódu

G+

'; document.getElementById('preroll-iframe').onload = function () { setupIframe(); } prerollContainer = document.getElementsByClassName('preroll-container-iframe')[0]; } function setupIframe() { prerollDocument = document.getElementById('preroll-iframe').contentWindow.document; let el = prerollDocument.createElement('style'); prerollDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:20px;right:25px}"; videoContent = prerollDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('PREROLL sound allowed'); // setUpIMA(true); videoContent.volume = 1; videoContent.muted = false; setUpIMA(); }).catch(function () { console.log('PREROLL sound forbidden'); videoContent.volume = 0; videoContent.muted = true; setUpIMA(); }); } } function setupDimensions() { prerollWidth = Math.min(iinfoPrerollPosition.offsetWidth, 480); prerollHeight = Math.min(iinfoPrerollPosition.offsetHeight, 320); } function setUpIMA() { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Preroll advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = prerollWidth; // adsRequest.linearAdSlotHeight = prerollHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. prerollDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( prerollDocument.getElementById('adContainer'), videoContent); } function unmutePrerollAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } } function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(prerollWidth, prerollHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } function onAdEvent(adEvent) { const ad = adEvent.getAd(); console.log('Preroll event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: if (!ad.isLinear()) { videoContent.play(); } prerollDocument.getElementById('adContainer').style.width = '100%'; prerollDocument.getElementById('adContainer').style.maxWidth = '640px'; prerollDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); if (ad.isLinear()) { intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } prerollDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (prerollLastError === 303) { playYtVideo(); } break; case google.ima.AdEvent.Type.COMPLETE: if (ad.isLinear()) { clearInterval(intervalTimer); } playYtVideo(); break; } } function onAdError(adErrorEvent) { console.log(adErrorEvent.getError()); prerollLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { playYtVideo(); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoPrerollPosition.remove(); playPrerollAd(); } else { return false; } adVolume = 1; return true; } function onContentPauseRequested() { videoContent.pause(); } function onContentResumeRequested() { videoContent.play(); } function onActiveView() { if (prerollContainer) { const containerOffset = prerollContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (prerollPaused) { adsManager.resume(); prerollPaused = false; } return true; } else { if (!prerollPaused) { adsManager.pause(); prerollPaused = true; } } } return false; } function playYtVideo() { iinfoPrerollPosition.remove(); youtubeIframe.style.display = 'block'; youtubeIframe.src += '&autoplay=1&mute=1'; } }