Programming of black box automatic test tool with API

Posted by gregor171 on Sun, 16 Jan 2022 16:19:52 +0100

1: A simple example

In the daily coding process, we often conduct automated testing. Automated testing here does not refer to unit testing, but simulates manual input for fast and highly concurrent testing. The automatic chemical industry that can be used has LOADRUNNER and a powerful test platform in VS2010 (recording operation steps and automatically generating code). However, mastering these tools also has a certain time cost, and, most importantly, it is not flexible enough for a programmer. Therefore, a more efficient way is to call WINDOWS API and write code by yourself.

Let's make a simple demonstration. For simplicity, suppose there is an application:

1: Provide a WINFORM form with a TextBox and a Button;

2: Click Button and a prompt box will pop up. The content of the prompt box is the value of TextBox;

Now, the test requirements are as follows:

1: Run the above program on 300 machines;

2: Click this Button on the 300 machines to see if function 2 above has been implemented;

Obviously, there is no such a simple program in the actual situation. The actual situation may be to click the Button to download a file uniformly, and the test requirements may become the load of the assessment server. At present, there are obviously no 300 people in the testing department sitting on the client to verify the test results. At this time, we need to provide an automated testing tool to complete the necessary testing tasks.

The test tool, first of all, is a C# program. Its main purpose is:

1: Obtain the window handle of the above application, and then obtain the TextBox handle and Button handle;

2: Fill in some characters randomly for TextBox;

3: Simulate clicking Button;

1.1: introduction to EnumChildWindows

Here we need to introduce EnumChildWindows,

EnumChildWindows is a good thing. You can enumerate all the child windows of a parent window:

BOOL EnumChildWindows(
  HWND hWndParent,         // Handle to parent window / / handle to parent window
  WNDENUMPROC lpEnumFunc,  // Callback function / / the address of the callback function
  LPARAM lParam            // Application defined value / / parameters defined by yourself
  );

It's that simple. Let's define another callback function, like the following:

BOOL CALLBACK EnumChildProc(
  HWND hwnd,      // handle to child window
  LPARAM lParam   // application-defined value
  );

When EnumChildWindows is called, it will be enumerated until the most child window is enumerated or the callback function returns false.

1.2: main source code of simple examples

The main codes of test tools are as follows:

private void button1_Click(object sender, EventArgs e)
  {
  //Gets the form handle of the test program
  IntPtr mainWnd = FindWindow(null, "FormLogin");
  List<IntPtr> listWnd = new List<IntPtr>();
  //Gets the handle to the OK button on the form
  IntPtr hwnd_button = FindWindowEx(mainWnd, new IntPtr(0), null, "OK");
  //Gets the handle to all controls on the form
  EnumChildWindows(mainWnd, new CallBack(delegate(IntPtr hwnd, int lParam)
  {
  listWnd.Add(hwnd);
  return true;
  }), 0);
  foreach (IntPtr item in listWnd)
  {
  if (item != hwnd_button)
  {
  char[] UserChar = "luminji".ToCharArray();
  foreach (char ch in UserChar)
  {
  SendChar(item, ch, 100);
  }
  }
  }
  SendMessage(hwnd_button, WM_CLICK, mainWnd, "0");
  }
  public void SendChar(IntPtr hand, char ch, int SleepTime)
  {
  PostMessage(hand, WM_CHAR, ch, 0);
  System.Threading.Thread.Sleep(SleepTime);
  }
  public static int WM_CHAR = 0x102;
  public static int WM_CLICK = 0x00F5;
  [DllImport("User32.dll", EntryPoint = "SendMessage")]
  public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam);
  [DllImport("user32.dll")]
  public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter,
  string lpszClass, string lpszWindow);
  [DllImport("user32.dll", SetLastError = true)]
  public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
  [DllImport("user32.dll")]
  public static extern int AnyPopup();
  [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
  [DllImport("user32.dll")]
  public static extern int EnumThreadWindows(IntPtr dwThreadId, CallBack lpfn, int lParam);
  [DllImport("user32.dll")]
  public static extern int EnumChildWindows(IntPtr hWndParent, CallBack lpfn, int lParam);
  [DllImport("user32.dll", CharSet = CharSet.Ansi)]
  public static extern IntPtr PostMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
  [DllImport("user32.dll", CharSet = CharSet.Ansi)]
  public static extern IntPtr SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
  [DllImport("user32.dll", CharSet = CharSet.Unicode)]
  public static extern IntPtr SendMessageA(IntPtr hwnd, int wMsg, int wParam, int lParam);
  [DllImport("user32.dll", CharSet = CharSet.Auto)]
  static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
  [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
  public static extern int GetWindowTextLength(IntPtr hWnd);
  [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
  public static extern IntPtr GetParent(IntPtr hWnd);
  public delegate bool CallBack(IntPtr hwnd, int lParam);

Finally: [may give you some help]

These materials should be the most comprehensive and complete preparation warehouse for [software testing] friends. This warehouse also accompanies tens of thousands of test engineers through the most difficult journey. I hope it can also help you!
Pay attention to my WeChat official account [software test dao] free access.

My learning and communication group: 644956177. There are technical cows in the group to communicate and share~

If my blog is helpful to you and you like my blog content, please click "like", "comment" and "collect" for three times!

Topics: software testing Testing