3GL   4GL   5GL  

  1. :
  2. , Tester
  3. Tester
  4. Tester
  5. Tester?

3 , . , , , , . SourceCode\ BugslayerUtil\Tests - , BUGSLAYERUTIL.DLL. , .

, (UI) . Tester, UI. , , Tester , . , Tester , , .

 

:

, Microsoft , , . 5000- <Alt>+<F>, <> , . , , , . , .

. , Recorder, Windows 3.x, 32- . Recorder ( ) , ( ). , (, , , , . .), -. .

, , . , , Recorder. Windows 3.x REC- . . , Recorder , . , WINFILE.EXE, , Recorder \System.

 if. . .then. . .else.

, . , , , YACC FLEX. , , Tester - , , ; (regression-testing) . Microsoft Visual Basic Scripting Edition (VBScript) Java Script (JScript), . Scripting Host (WSH) , . , Tester.

 

, Tester

, Tester , , : , . , , , . Tester .

Tester:

1. , ().

2. , , VB- sendKeys, Tester .

3. Tester .

4. HWND Tester .

5. Tester , .

6. Tester .

7. Tester .

, . , , , , : "" , . . , . , , UI . , , UI "", . , , UI "".

Tester, , 20 (Quality Assurance QA). , , . , Tester . GUI- WDBG, 4, !

 

Tester

Tester . Tester-, , , . 13-1 VBScript-, (NOTEPAD.EXE), .

 

  13-1. Tester- 

' VBScript Tester.

' , .

' .

Dim tSystem

Dim tInput

Dim twin

Set tSystem = «Script.CreateObject ( "Tester.TSystem")

Set tInput = WScript.CreateObject ( "Tester.TInput")

' .

tSystem.Execute "NOTEPAD.EXE"

' 200 .

tSystem.Pause 200

' .

Set twin = tSystem.FindTopWindowByTitle ( "Untitled - Notepad")

If ( twin Is Nothing) Then

MsgBox "Unable to find Notepad!" 

WScript.Quit

 End If

' , .

twin.SetForegroundTWindow

' () .

tlnput.PlayKeys "Be all you can be!~ ~ ~"

' .

tlnput.PlayKeys "Put on your boots and parachutes....~ ~ ~"

' .

tlnput.PlayKeys "Silver wings upon their chests.....~ ~ ~"

' 1 .

tSystem.Pause 1000

' .

tlnput.PlayKeys "%FX"

tSystem.Pause 50

tlnput.PlayKeys "{TAB}~"

' !

13-1 , Tester . TSystem , . TWindow, FindTopWindowByritie 13-1, " ". HWND ( ), . , TWindow , . Tlnput, PlayKeys, , .

13-2 TNotify, VBScript-. , , . TNotify , , . , 13-2, "".

  13-2. TNotify VBScript 

' VBScript-

' TNotify.AddNotification .

' Visual Basic 6, enum .

Const antDestroyWindow = 1

Const antCreateWindow = 2

Const antCreateAndDestroy = 3

Const ansExactMatch = 0

Const ansBeginMatch = 1

Const ansAnyLocMatch = 2

' tSystem tInput.

Dim tSystem

Dim tInput

Set tSystem = WScript.CreateObject ( "Tester.TSystem")

Set tlnput = WScript.CreateObject ( "Tester.Tlnput")

' TNotify

Dim Notifier

' TNotify.

Set Notifier =

WScript.CreateObject ( "Tester.TNotify" ,' _

"NotepadNotification_" )

' .

' window destroy ( )

'window create ( ).  

'. TNotify .

Notifier.AddNotification antCreateAndDestroy, _

ansAnyLocMatch , 

_ "Notepad"

' .

 tSystem.Execute "NOTEPAD.EXE" 

' .

 tSystem.Pause 500

' - Visual Basic ,

 ' Because Visual Basic isn't thread-safe

' , .

 ' ,

 ' .  

' window create window destroy.

 Notifier.CheckNotification

' NotepadNotification_CreateWindow

 ' ,  

', ,

 tInput.PlayKeys "%FX"

 tSystem.Pause 50

 tlnput.PlayKeys "{TAB}-" 

' . 

Notifier.CheckNotification

' TNotify .

 tSystem.Pause 100

' . WSH,

 ' ,

 ' . 

WScript.DisconnectObject Notifier 

Set Notifier = Nothing

Sub NotepadNotificationCreateWindow ( twin)

MsgBox ( "Notepad was created!")

 End Sub 

Sub NotepadNotificationDestroyWindow ()

MsgBox ( "Notepad has gone away....")

 End Sub

TNotify checkNotification. ( , " Tester" ). checkNotification , , , , , . 13-2 , , , , , .

, , TNotify , File Save. TNotify . , , , , , . , , "", , . , TNotify AddNotification . CreateWindow TWindow-, , . DestroyWindow, , , , , , .

 , -, , , . .

- Tester. , NPAD_TEST.VBS VBScript-, . ( Tester Tester'a) Tester, . TESTER.VBG.TT VB-, Tester'a Visual Basic. , TWindows, , TWindow.

VBScript , , . VBScript- VBScript , Visual Basic, . VBScript , . , , Visual Basic, , . , Tester , (MASM), VBScript.

Tester'e , , . . , . , , . . , : , . , , . , .

Tester'a, : " , ?". , , , , . Windows (WSH- CSCRIPT.EXE), , wscript.Echo, . , ( WinDiff); - , . , , . , , , .

Tester'a? Tester , a Visual Basic , , Tinput.piayKeys. , , , . , piayKeys , , ( TWindow.SetForegroundTWindow). , SetForegroundTwindow, .

 

Tester

Tester'a, . Tester'a C++ (Active Template Library ATL), , Visual Basic. , Tester'e, , . Visual Basic, , , , .

Tinput, , . , , VB- SendKeys. , , Microsoft Outlook 2000, , . SendKeys , PiayKeys. , , , Microsoft Windows 98 2000 Sendinput. Windows NT 4, Service Pack 3 ( ). Sendinput Microsoft Active Accessibility (MSAA) , keybd_event. Sendinput , . ( ), , . Tester'a. , Sendinput Outlook 2000.

. Visual Basic sendKeys , piayKeys , . , , , , SourceCode\Tester\TInputHlp -. Tinput, Tester C++ ++- (DLL). Tinput. PiayKeys VB-- DLL.

TWindow, Twindows TSystem . Visual Basic API- Windows. TNotify, . , , , , . , , , "" .

, 1. , SDK- , - . , . HCBT_CREATEWND, . , -, , WM_CREATE, . HCBT_CREATEWND . - .

  computer-based training, .

, . , WM_CREATE . WM_SETTEXT. , , WM_SETTEXT. , () , WM_SETTEXT . : , Microsoft Internet Explorer, WM_SETTEXT .

, WM_SETTEXT ( WM_CREATE), , . WH_CALLWNDPROCRET. WM_CREATE, WM_SETTEXT. WM_DESTROY. WM_DESTROY, . . , , . , , WM_NCDESTROY.

"" "" WM_SETTEXT , , WM_S-. (state machine), . , . WM_ST- , . , TNotify- , "", NOTEPAD.EXE, , NOTEPAD.EXE . , "--" , "" . , TNotify-; .

Tester Visual Basic , TNotify. , Tnotify, , checkNotification. , Visual Basic , , , TESTER.DLL.

, :

: - . , DLL - TESTER.DLL, Visual Basic. , Visual Basic- , .

, 16- Windows-, , API- setTimer. , . , TNotify, , , .

, , , TNotify. , , WM_TIMER , checkNotification, . , TSystem. Pause, DoEvents ( TSystem. Pause) . , DoEvents TSystem.pause , CheckNotification.

, , , Tester. 13-3 - TNOTIFYHLP.CPP. Tester'a TNOTIFY. BAS , , TNOTIFY.CLS. TNotify , TNotify , , . (.HOOKDATA), . , , " ".

13-3.TNOTIFY. 

/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

"Debugging Applications" (Microsoft Press)

Copyright (c) 1997-2000 John Robbins All rights reserved.

TNotifyHlp.dll

- - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - * /

#include <tchar.h>

 #include <windows.h> 

#include "TNotifyHlp.h" 

/*///////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////*/

 //  

static const int TOTAL_NOTIFY_SLOTS = 5; 

//

static const LPCTSTR k_MUTEX_NAME = _T ( "TNotifyHlp_Mutex");

 //  

static const int k_WAITLIMIT = 5000;

// TRACE

 // BugslayerUtil.DLL

 // .

 #ifdef _DEBUG

#define TRACE ::OutputDebugString

 #else

#define TRACE (void)0

#endif

/*//////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////*/ 

//  

typedef struct tagJTNOTIFYITEM 

{

// PID ,

DWORD dwOwnerPID ;

//

int iNotifyType;

//

int iSearchType;

// HWND-

HWND hWndCreate ;

//

BOOL bDestroy ;

//

TCHAR szTitle [ _ ];

 } TNOTIFYITEM, * PTNOTIFYITEM;

 /*///////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////*/ 

// ,

 // .

// HINSTANCE- .  

// DLL. 

static HINSTANCE gjnlnst = NULL; 

// , g_NotifyData 

static HANDLE g_hMutex = NULL;

// .

 // , . .

 // .

static HHOOK g_hHook = NULL;

// , , 

// , ,

 static int g_iThisProcess!tems = 0; 

/*/////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////*/ 

//

LRESULT CALLBACK CallWndRetProcHook ( int nCode ,

WPARAM wParam, 

LPARAM IParam );

//

static LONG _stdcall CheckNotifyltem ( HANDLE hltem, BOOL bCreate);

 /*//////////////////////////////////////////////////////////////// 

()

/////////////////////////////////////////////////////////////////*/

 #pragma data_seg ( ". HOOKDATA")

 //

static TNOTIFYITEM g_shared_NotifyData [ TOTAL_NOTIFY_SLOTS ] = 

{ 0,0 , 0, NULL, 0, '\0' }, 

{ 0, 0, 0, NULL, 0, '\0' }, 

{ 0, 0, 0, NULL, 0, '\0' },

 { 0, 0, 0, NULL, 0, '\0' }, 

{ 0, 0, 0, NULL, 0, '\0' } 

};

//

 static int g_shared_iUsedSlots = 0;

 #pragma data_seg ()

/*////////////////////////////////////////////////////

///////////////////////////////////////////////////*/ 

extern "C" BOOL WINAPI DllMain ( HINSTANCE hlnst ,

DWORD dwReason , 

LPVOID /*lpReserved*/)

 {

 #ifdef _DEBUG

BOOL bCHRet;

 #endif

BOOL bRet = TRUE;

 switch ( dwReason) 

{

case DLL_PROCESS_ATTACH :

// .

g_hlnst = hlnst;

// .

DisableThreadLibraryCalls ( g_hlnst);

// . ,

// .

g_hMutex = CreateMutex ( NULL, FALSE, k_MUTEX_NAME);

if ( NULL == g_hMutex)

{

TRACE ( _T ( "Unable to create the mutex!\n")); 

// ,  

// , DLL.

 bRet = FALSE; }

break; 

case DLL_PROCESS_DETACH :

// , -

 // . , ,

 // (orphan) .

 if (0 != g_iThisProcess!tems) 

{

DWORD dwProcID = GetCurrentProcessId ();

// ,

// DLL_PROCESS_DETACH

// .

// .

for ( int i = 0; i < TOTAL_NOTIFY_SLOTS; i++)

(

if ( g_shared_NotifyData[i].dwOwnerPID == dwProcID) 

#ifdef __DEBUG

TCHAR szBuff[ 50 ] ; 

wsprintf ( szBuff,

_T( "DLL_PROCESS_DETACH removing : #%d\n"),

i);

TRACE ( szBuff);

 #endif

// . RemoveNotifyTitle ( (HANDLE)i); 

}

// .

 #ifdef _DEBUG

bCHRet =

 #endif

CloseHandle ( g_hMutex);

 #ifdef _DEBUG

 if ( FALSE == bCHRet) 

{

TRACE ( "!!!!!!!!!!!!!!!!!!!!!!!!\n"); 

TRACE { "CloseHandle(gJiMutex) "

"failed!!!!!!!!!!!!!!!!!!\n"); 

TRACE ( "!!!!!!!!!!!!!!!!!!!!!!!!\n");

 }

#endif

break; 

default :

break; 

}

return ( bRet); 

}

HANDLE TNOTIFYHLP_DLLINTERFACE _stdcall

 AddNotifyTitle ( int iNotifyType, 

int iSearchType, 

LPCTSTR szString )

 {

// , , 

if ( ( iNotifyType < ANTN_DESTROYWINDOW ) || 

( iNotifyType > ANTN_CREATEANDDESTROY ) ) 

{

TRACE ( "AddNotify Title : iNotifyType is out of range!\n"); 

return ( INVALID_HANDLE_VALUE); 

}

// , ,

 if ( ( iSearchType < ANTS_EXACTMATCH ) || 

( iSearchType > ANTS_ANYLOCMATCH) )

{

TRACE ( "AddNotify Title : iSearchType is out of range!\n");

return ( INVALID_HANDLE_VALUE); 

}

// , , 

if ( TRUE == IsBadStringPtr ( szString, MAX_PATH)) 

{

TRACE ( "AddNotify Title : szString is invalid!\n");

return ( INVALID_HANDLE_VALUE); 

}

// .

DWORD dwRet = WaitForSingleObject ( g_hMutex, k_WAITLIMIT);

 if ( WAIT_TIMEOUT == dwRet) 

{

TRACE ( _T( "AddNotifyTitle : Wait on mutex timed out!!\n"));

return ( INVALID_HANDLE_VALUE); 

}

// , .

 if ( TOTAL_NOTIFY_SLOTS == g_shared_iUsedSlots) 

{

ReleaseMutex ( g_hMutex);

return ( INVALID_HANDLE_VALUE); 

}

// ,

 for ( int i = 0; i < TOTAL_NOTIFY_SLOTS; i++)

{

if ( _T ( '\0') == g_shared_NotifyData[ i ].szTitle[ 0 ])

{

 break;

}

 }

// .

g_shared_NotifyData[ i ].dwOwnerPID = GetCurrentProcessId ();

 g_shared_NotifyData[ i ].iNotifyType = iNotifyType; 

g__shared_NotifyData[ i ].iSearchType = iSearchType;

 Istrcpy ( g_shared__Notif yData [ i J.szTitle, szString); 

//

. g_shared_iUsedSlots++;

 // . 

g_iThis Process Items++;

TRACE ( "AddNotifyTitle - Added a new item!\n"); 

ReleaseMutex ( g_hMutex);

// , .

 if ( NULL = g_hHook)

 {

g_hHook = SetWindowsHookEx ( WH_CALLWNDPROCRET ,

CallWndRetProcHook, g_hlnst , 0 );

 #ifdef _DEBUG

if ( NULL == g_hHook)

 {

char szBuff[ 50 ];

 wsprintf ( szBuff,

_T ( "SetWindowsHookEx failed!!!! (Ox%08X)\n"), GetLastError ()); 

TRACE ( szBuff); 

}

#endif 

}

return ( (HANDLE)!); 

void TNOTIFYHLP_DLLINTERFACE _stdcall

RemoveNotifyTitle ( HANDLE hltem) 

{

// .

int i = (int)hltem;

if ( ( i < 0) || ( i > TOTAL_NOTIFY_SLOTS))

{

TRACE ( _T ( "RemoveNotifyTitle : Invalid handle!\n"));

  return; 

}

// .

DWORD dwRet = WaitForSingleObject ( g_hMutex, k_WAITLIMIT);

 if ( WAIT_TIMEOUT == dwRet) 

{

TRACE ( _T ( "RemoveNotifyTitle : Wait on mutex timed out!\n"));

  return; 

}

if ( 0 = g_shared_iUsedSlots) 

{

TRACE ( _T ( "RemoveNotifyTitle : Attempting to remove when "

"no notification handles are set!\n")); 

ReleaseMutex ( g_hMutex);

  return; 

}

// -, ,  

// NotifyData, .

 //

 // , .

if ( 0 == g_shared_NotifyData[ i ].dwOwnerPID) 

{

TRACE ( "RemoveNotifyTitle : Attempting to double remove!\n");

ReleaseMutex ( g_hMutex);

return; 

}

// . 

g_shared_NotifyData[ i ].dwOwnerPID =0; 

g_shared_NotifyData[ i ].iNotifyType = 0;

 g_share.d_NotifyData [ i ] .hWndCreate = NULL;

 g_shared_NotifyData[ i ].bDestroy = FALSE; 

g_shared_NotifyData[ i ].iSearchType = 0;

 g_shared_NotifyData[ i ].szTitle[ 0 ] = _T ( '\0');

 // .

 g_shared_iUsedSlots- -;

// .

 g_iThisProcessItems- -;

TRACE ( _ ( "RemoveNotifyTitle - Removed an item!\n")); 

ReleaseMutex ( g_hMutex);

// ,  

// .

if ( ( 0 == g_iThisProcess!tems) && ( NULL != g_hHook)) 

{

if ( FALSE = UnhookWindowsHookEx ( g_hHook))

{

TRACE ( _T ( "UnhookWindowsHookEx failed!\n"));

}

g_hHook = NULL; 

} HWND TNOTIFYHLP_DLLINTERFACE _stdcall

CheckNotifyCreateTitle ( HANDLE hltem)

{

return ( (HWND)CheckNotifyltem ( hltem, TRUE));

}

BOOL TNOTIFYHLP_DLLINTERFACE _stdcall

CheckNotifyDestroyTitle ( HANDLE hltem) 

{

return ( (BOOL)CheckNotifyltem ( hltem, FALSE)); 

/*///////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////*/ 

static LONG _stdcall CheckNotifyltem { HANDLE hltem, BOOL bCreate)

{

// .

int i = (int)hltem;

if ( ( i < 0) || ( i > TOTAL_NOTIFY_SLOTS))

{

TRACE ( _T ( "CheckNotifyltem : Invalid handle!\n"));

return ( NULL); 

}

LONG IRet = 0; 

// .

DWORD dwRet = WaitForSingleObject ( g_hMutex, k_WAITLIMIT);

 if ( WAIT_TIMEOUT == dwRet) 

{

TRACE ( _T ( "CheckNotifyltem : Wait on mutex timed out!\n"));

return ( NULL);

 }

// , .

 if ( 0 = g_shared_iUsedSlots) 

{

ReleaseMutex ( g_hMutex);

return ( NULL); 

}

// , 

if ( TRUE == bCreate)

 {

// HWND- NULL,

// .

if ( NULL != g_shared_NotifyData[ i ].hWndCreate)

{

IRet = (LONG)g_shared_NotifyData[ i ].hWndCreate; 

g_shared_NotifyData[ i ].hWndCreate = NULL;

}

 }

else 

{

if ( FALSE != g_shared_NotifyData[ i ].bDestroy)

{

IRet = TRUE;

g_shared_NotifyData[ i ].bDestroy = FALSE;

}

ReleaseMutex ( g_hMutex); 

return ( IRet); 

}

static void _stdcall CheckTableMatch ( int iNotifyType,

HWND hWnd , 

LPCTSTR szTitle ) {

// .

DWORD dwRet = WaitForSingleObject ( g__hMutex, k_WAITLIMIT);

if ( WAIT_TIMEOUT == dwRet)

{

TRACE ( _T ( "CheckTableMatch : Wait on mutex timed out!\n"));

  return; 

}

// , . 

if ( 0 == g_shared_iUsedSlots) 

{

ReleaseMutex ( g_hMutex);

TRACE { _T ( "CheckTableMatch called on an empty table!\n")); 

return;

 }

// .

for ( int i = 0; i < TOTAL_NOTIFY_SLOTS; i++) 

{

// -  

// ?

if- ( ( _ ( '\0') != g_shared_NotifyData[ i ].szTitle[ 0 ]) && 

( g__shared_NotifyData[ i ].iNotifyType & iNotifyType ) ) 

{

BOOL bMatch = FALSE;

// .

switch ( g_shared_NotifyData[ i ].iSearchType)

{

case ANTS_EXACTMATCH :

 // , 

if ( 0 = Istrcmp ( g_shared_NotifyData[i].szTitle,

szTitle )) 

{

bMatch = TRUE; 

}

break;

case ANTS_BEGINMATCH : 

if ( 0 ==

 _tcsnccmp ( g_shared_NotifyData[i].szTitle, 

 szTitle , strlen(g_shared_NotifyData[i].szTitle))) 

{

bMatch = TRUE;

 }

break; case ANTS_ANYLOCMATCH :

if ( NULL != _tcsstr ( szTitle

g_shared_NotifyData[i].szTitle)) 

{

bMatch = TRUE; 

}

break; 

default :

TRACE ( _T ( "CheckTableMatch invalid "\ "search type!!!\n"));

 ReleaseMutex ( g_hMutex);

  return; 

break; 

}

// ?

 if ( TRUE = bMatch) 

{

// , "1"

// .

if ( ANTN_DESTROYWINDOW == iNotifyType)

{

g_shared_NotifyData[ i ].bDestroy = TRUE;

 }

else 

{

// , HWND.

 g_shared_NotifyData[ i ].hWndCreate - hWnd;

 } 

}

ReleaseMutex ( g_hMutex);

 }

LRESULT CALLBACK CallWndRetProcHook ( int nCode ,

WPARAM wParam,

 LPARAM IParam ) 

{

//

TCHAR szBuff[ _ ];

// ,

// - .

LRESULT IRet = CallNextHookEx ( gJnHook, nCode, wParam, IParam);

// The docs say never to mess around with a negative code, so I don't.

//

// , .

if ( nCode < 0) 

{

return ( IRet);

 }

// . ( )

 // ?  

// ole-  

// /? 

PCWPRETSTRUCT pMsg = (PCWPRETSTRUCT)IParam; 

// ,

LONG IStyle = GetWindowLong ( pMsg->hwnd, GWL_STYLE); 

if ( WS_CAPTION != ( IStyle & WS_CAPTION)) {

return ( IRet); 

}

// WM_DESTROY ,

 // .

 // .

if ( WM_DESTROY == pMsg->message) 

{

if (0 != GetWindowText ( pMsg->hwnd, szBuff, MAX_PATH))

{

CheckTableMatch ( ANTN_DESTROYWINDOW, pMsg->hwnd, szBuff);

}

return ( IRet); 

}

// , .

 // . , 

// WM_INITDIALOG.

 if ( 0 == GetClassName ( pMsg->hwnd, szBuff, MAX_PATH)) 

{

#iifdef _DEBUG

TCHAR szBuff[ 50 ];

wsprintf ( szBuff ,

 _T ( "GetClassName failed for HWND : 0x%08X\n"), 

pMsg->hwnd ) ;

TRACE ( szBuff); 

#endif

//He ,

return ( IRet); 

}

if ( 0 == Istrcmpi ( szBuff, _T ( "#32770"))) 

{

// , ,

// - WM_INITDIALOG.

if ( WM_INITDIALOG == pMsg->message)

{

// .

if (0 != GetWindowText ( pMsg->hwnd, szBuff, MAX_PATH))

{

CheckTableMatch ( ANTN_CREATEWINDOW,

 pMsg->hwnd ,

 szBuff );

 } 

}

return ( IRet); 

}

//

// .

 // , , 

if ( WM_CREATE == pMsg->message) 

{

//

// WM_CREATE.

// WM_SETTEXT, .

if (0 != GetWindowText ( pMsg->hwnd, szBuff, MAX_PATH))

{

CheckTableMatch ( ANTN_CREATEWINDOW, 

pMsg->hwnd , 

szBuff ); 

}

 }

else if ( WM_SETTEXT = pMsg->message)

 {

// WM_SETTEXT,

// . ,

// , Internet Explorer, WM_SETTEXT

// ' .

// , WM_SETTEXT ,

//

// ,

// WM_SETTEXT.

if ( NULL != pMsg->lParam)

{

CheckTableMatch ( ANTN_CREATEWINDOW , 

pMsg->hwnd , 

(LPCTSTR)pMsg->lParam ); 

}

return ( IRet); 

}

TNotify , - , . , , . Microsoft Visual C++, . SoftlCE. . , printf- . DBGVIEW OutputDebugString , , .

Tester'a, Windows 98. - Windows NT 4 Windows 2000, Windows 98 TWindows. HWND , Add, iswindow. , iswindow BOOL. , TRUE , FALSE . , 1 = iswindow (hWndT), , , . , . "", .

 

Tester?

, Tester : . , Tester'a, , , . , :

(UI) . (Tester), , . , , Tester, , ( ).

, Tester , , . , . , , , , (QA-) QA- .

        3GL   4GL   5GL  

, - , , .




 10.11.2021 - 12:37: - Personalias -> WHO IS WHO - - _.
10.11.2021 - 12:36: - Conscience -> . ? - _.
10.11.2021 - 12:36: , , - Upbringing, Inlightening, Education -> ... - _.
10.11.2021 - 12:35: - Ecology -> - _.
10.11.2021 - 12:34: , - War, Politics and Science -> - _.
10.11.2021 - 12:34: , - War, Politics and Science -> . - _.
10.11.2021 - 12:34: , , - Upbringing, Inlightening, Education -> , - _.
10.11.2021 - 09:18: - New Technologies -> , 5G- - _.
10.11.2021 - 09:18: - Ecology -> - _.
10.11.2021 - 09:16: - Ecology -> - _.
10.11.2021 - 09:15: , , - Upbringing, Inlightening, Education -> - _.
10.11.2021 - 09:13: , , - Upbringing, Inlightening, Education -> - _.
Bourabai Research -  XXI Bourabai Research Institution