实现Python虚拟按键解决getch()的自动化测试问题
来源:互联网 发布:淘宝刷关注软件 编辑:程序博客网 时间:2024/06/05 02:29
之前由于项目组的smoke test太过频繁,而且这些工具大部分功能都是通过命令行执行的,这么便利的条件下不做一套自动测试脚本真是没有天理了!
在开发过程中发现一个问题:代码中同时使用了getchar()和getch()两个函数,从自动测试角度看,getchar()好处理,它的来源是缓冲区,利用python的管道很容易搞定,而getch()就麻烦了,它是直接来源于键盘中断,管道在这里就没用了....
这怎么办呢?思来想去只能实现一个虚拟键盘来解决这个问题了,在Windows中还好,有一个现成的python模块可以利用,直接调用Windows API调用虚拟键盘,你可以在这里找到它:http://sourceforge.net/projects/pywin32/files%2Fpywin32/。在linux里比较麻烦,好像没有现成的python模块支持,没办法只能自己写个小程序实现了,简单起见,还是用c吧,这个比较熟悉...
首先是linux下虚拟键盘的C代码实现:
#include <linux/input.h>#include <time.h>#include <fcntl.h>#include <string.h>#include <errno.h>#include <stdio.h>typedef struct Ascii2KeyCode{unsigned char ascii;int keycode_sum;unsigned int keycode[3];}Ascii2KeyCode_t;#define Backspace 14#define Shift 42 #define Control 29 #define Alt 56 #define CapsLock 58#define Esc 1 #define PageUp 104 #define PageDown 109#define End 107 #define Home 102 #define Insert 110 #define Delete 111 #define Help 138 #define NumLock 69 Ascii2KeyCode_t ascii2keycode_map[] = {{'\t', 1, {15,}},{'\n', 1, {28,}},{'\'', 1, {40,}},{'\\', 1, {43,}},{'\"', 2, {Shift,40}},{' ', 1, {57,}},{'!', 2, {Shift,2,}},{'#', 2, {Shift,4,}},{'$', 2, {Shift,5,}},{'%', 2, {Shift,6,}},{'&', 2, {Shift,8,}},{'(', 2, {Shift,10,}},{')', 2, {Shift,11,}},{'*', 2, {Shift,9,}},{'+', 2, {Shift,13,}},{',', 1, {51,}},{'-', 1, {12,}},{'.', 1, {52,}},{'/', 1, {53,}},{'0', 1, {11,}},{'1', 1, {2,}},{'2', 1, {3,}},{'3', 1, {4,}},{'4', 1, {5,}},{'5', 1, {6,}},{'6', 1, {7,}},{'7', 1, {8,}},{'8', 1, {9,}},{'9', 1, {10,}},{':', 2, {Shift,39,}},{';', 1, {39,}},{'<', 2, {Shift,51,}},{'=', 1, {13,}},{'>', 2, {Shift,52,}},{'?', 2, {Shift,53,}},{'@', 2, {Shift,3,}},{'A', 2, {Shift,30,}},{'B', 2, {Shift,48,}},{'C', 2, {Shift,46,}},{'D', 2, {Shift,32,}},{'E', 2, {Shift,18,}},{'F', 2, {Shift,33,}},{'G', 2, {Shift,34,}},{'H', 2, {Shift,35,}},{'I', 2, {Shift,23,}},{'J', 2, {Shift,36,}},{'K', 2, {Shift,37,}},{'L', 2, {Shift,38,}},{'M', 2, {Shift,50,}},{'N', 2, {Shift,49,}},{'O', 2, {Shift,24,}},{'P', 2, {Shift,25,}},{'Q', 2, {Shift,16,}},{'R', 2, {Shift,19,}},{'S', 2, {Shift,31,}},{'T', 2, {Shift,20,}},{'U', 2, {Shift,22,}},{'V', 2, {Shift,47,}},{'W', 2, {Shift,17,}},{'X', 2, {Shift,45,}},{'Y', 2, {Shift,21,}},{'Z', 2, {Shift,44,}},{'[', 1, {26,}},{']', 1, {27,}},{'^', 2, {Shift,7,}},{'_', 2, {Shift,12,}},{'`', 1, {41,}},{'a', 1, {30,}},{'b', 1, {48,}},{'c', 1, {46,}},{'d', 1, {32,}},{'e', 1, {18,}},{'f', 1, {33,}},{'g', 1, {34,}},{'h', 1, {35,}},{'i', 1, {23,}},{'j', 1, {36,}},{'k', 1, {37,}},{'l', 1, {38,}},{'m', 1, {50,}},{'n', 1, {49,}},{'o', 1, {24,}},{'p', 1, {25,}},{'q', 1, {16,}},{'r', 1, {19,}},{'s', 1, {31,}},{'t', 1, {20,}},{'u', 1, {22,}},{'v', 1, {47,}},{'w', 1, {17,}},{'x', 1, {45,}},{'y', 1, {21,}},{'z', 1, {44,}},{'{', 2, {Shift,26,}},{'|', 2, {Shift,43,}},{'}', 2, {Shift,27,}},{'~', 2, {Shift,41,}},};void simulate_key(int fd, unsigned int keycode, int keyvalue){struct input_event event,ev;event.type = EV_KEY;event.code = keycode;event.value = keyvalue;gettimeofday(&event.time, 0);memset(&ev, 0, sizeof(ev));if (write(fd, &event, sizeof(event)) < 0) {printf("simulate key error\n");write(fd, &ev, sizeof(ev));return;}write(fd, &ev, sizeof(ev));}void input_char(int fd, char ch_input){int i = 0, j = 0;Ascii2KeyCode_t keycode = {};for (i=0; i<sizeof(ascii2keycode_map)/sizeof(Ascii2KeyCode_t); i++){if (ch_input == ascii2keycode_map[i].ascii){keycode = ascii2keycode_map[i];// Key downfor (j=0; j<keycode.keycode_sum; j++){simulate_key(fd, keycode.keycode[j], 1);}// Key upfor (j=keycode.keycode_sum; j>0; j--){simulate_key(fd, keycode.keycode[j-1], 0);}break;}}}int main ( int argc, char *argv[] ){if (argc < 3){printf("Please input as this : ./virtkeyboard /dev/input/event1 \"12324\"\n");return -1;}// Open device int fd_kbd = open(argv[1], O_RDWR);if(fd_kbd <= 0) {printf("error open keyboard:%s\n", strerror(errno));return -1;}// Input chars one-by-onechar *pt = argv[2];for (pt=argv[2]; *pt!='\0'; pt++){input_char(fd_kbd, *pt);}// Close deviceclose(fd_kbd);return 0;}用gcc编译,命名为“virtkeyboard”,然后copy到/usr/local/bin下,或者把存放路径加到PATH变量中。下面是python模块,屏蔽Windows和linux差异,实现虚拟键盘:
import platformimport timeimport subprocessif (platform.system().lower().find("windows") != -1): Backspace = 8 Shift = 16 Control = 17 Alt = 18 CapsLock = 20 Esc = 27 PageUp = 33 PageDown = 34 End = 35 Home = 36 Insert = 45 Delete = 46 Help = 47 NumLock = 144 Ascii2KeyCode = {\ b'\t':[9,], \ b'\n':[13,], \ b'\'':[222,], \ b'\\':[220,], \ b'\"':[Shift,222,],\ b' ':[32,], \ b'!':[Shift,49,], \ b'#':[Shift,51,], \ b'$':[Shift,52,], \ b'%':[Shift,53,], \ b'&':[Shift,55,], \ b'(':[Shift,57,], \ b')':[Shift,48,], \ b'*':[Shift,56,], \ b'+':[Shift,187,],\ b',':[188,], \ b'-':[189,], \ b'.':[190,], \ b'/':[191,], \ b'0':[48,], \ b'1':[49,], \ b'2':[50,], \ b'3':[51,], \ b'4':[52,], \ b'5':[53,], \ b'6':[54,], \ b'7':[55,], \ b'8':[56,], \ b'9':[57,], \ b':':[Shift,186,],\ b';':[186,], \ b'<':[Shift,188,],\ b'=':[187,], \ b'>':[Shift,190,],\ b'?':[Shift,191,],\ b'@':[Shift,50,], \ b'A':[Shift,65,], \ b'B':[Shift,66,], \ b'C':[Shift,67,], \ b'D':[Shift,68,], \ b'E':[Shift,69,], \ b'F':[Shift,70,], \ b'G':[Shift,71,], \ b'H':[Shift,72,], \ b'I':[Shift,73,], \ b'J':[Shift,74,], \ b'K':[Shift,75,], \ b'L':[Shift,76,], \ b'M':[Shift,77,], \ b'N':[Shift,78,], \ b'O':[Shift,79,], \ b'P':[Shift,80,], \ b'Q':[Shift,81,], \ b'R':[Shift,82,], \ b'S':[Shift,83,], \ b'T':[Shift,84,], \ b'U':[Shift,85,], \ b'V':[Shift,86,], \ b'W':[Shift,87,], \ b'X':[Shift,88,], \ b'Y':[Shift,89,], \ b'Z':[Shift,90,], \ b'[':[219,], \ b']':[221,], \ b'^':[Shift,54,], \ b'_':[Shift,189,],\ b'`':[192,], \ b'a':[65,], \ b'b':[66,], \ b'c':[67,], \ b'd':[68,], \ b'e':[69,], \ b'f':[70,], \ b'g':[71,], \ b'h':[72,], \ b'i':[73,], \ b'j':[74,], \ b'k':[75,], \ b'l':[76,], \ b'm':[77,], \ b'n':[78,], \ b'o':[79,], \ b'p':[80,], \ b'q':[81,], \ b'r':[82,], \ b's':[83,], \ b't':[84,], \ b'u':[85,], \ b'v':[86,], \ b'w':[87,], \ b'x':[88,], \ b'y':[89,], \ b'z':[90,], \ b'{':[Shift,219,],\ b'|':[Shift,220,],\ b'}':[Shift,221,],\ b'~':[Shift,192,],\ }if (platform.system().lower().find("windows") != -1): import win32api import win32con def KeyDown(keyCode): if (platform.system().lower().find("windows") != -1): win32api.keybd_event(keyCode,0,0,0)def KeyUp(keyCode): if (platform.system().lower().find("windows") != -1): win32api.keybd_event(keyCode,0,win32con.KEYEVENTF_KEYUP,0)def InputChar(char=b''): if (len(char) < 1): return None keyCodeList = Ascii2KeyCode.get(char) if (keyCodeList == None): print('Can not found char\'s key code : ' + char) return None for keyCode in keyCodeList: KeyDown(keyCode) for keyCode in keyCodeList[::-1]: KeyUp(keyCode) return char def FindKeyDevice(): if (platform.system().lower().find("linux") != -1): commandLine = ['cat', '/proc/bus/input/devices'] proc = subprocess.Popen(commandLine, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = proc.communicate() devInfoLines = out.decode().splitlines() index = 0 while (index < len(devInfoLines)): lineStr = devInfoLines[index].strip() if (len(lineStr) < 1): index += 1 continue splitArry = lineStr.split(':') if (len(splitArry) < 2): index += 1 continue if (splitArry[0].strip() == 'N'): nameSplitArry = splitArry[1].split('=', 1) if (len(nameSplitArry) < 2) or (nameSplitArry[0].strip() != 'Name'): index += 1 continue if (nameSplitArry[1].lower().find('keyboard') != -1) and (nameSplitArry[1].lower().find('virtual') == -1): index += 4 if (index >= len(devInfoLines)): print('Can not found keyboard device !') return None lineStr = devInfoLines[index].strip() splitArry = lineStr.split(':') if (len(splitArry) < 2): index += 1 continue if (splitArry[0].strip() == 'H'): handlSplitArry = splitArry[1].split('=', 1) if (len(handlSplitArry) < 2) or (handlSplitArry[0].strip() != 'Handlers') or (handlSplitArry[1].lower().find('event') == -1): index += 1 continue devSplitArry = handlSplitArry[1].split(' ') for devStr in devSplitArry: if (devStr.lower().find('event') != -1): return devStr index += 1 return None def InputString(inputStr=b''): if (platform.system().lower().find("windows") != -1): for char in inputStr: keyCode = ord(char) InputChar(char) return inputStr elif (platform.system().lower().find("linux") != -1): keyDev = FindKeyDevice() if (keyDev == None): print('Can not found key device !') return None keyDev = '/dev/input/' + keyDev keyInputStr = '' + inputStr commandLine = ['virtkeyboard', keyDev, keyInputStr] proc = subprocess.Popen(commandLine, shell=False) proc.wait() else: return None if __name__ == '__main__': InputString('auto_test\"sdfsdgsdggasd')
Windows下要先安装pywin32,然后就可以随心所欲发你想要的字符了!不过这里有个问题,由于是键盘中断,linux中每个终端貌似都能收到键盘输入事件,windows好像只有当前有效窗口能收到,以后再考虑吧,至少已经满足当前需求了。
1 0
- 实现Python虚拟按键解决getch()的自动化测试问题
- 解决虚拟按键遮盖底部视图的问题
- 解决华为手机隐藏虚拟按键Activity被重启的问题
- 公司自动化测试--需要解决的问题。
- 自动化测试接口的实现,基于python
- 关于 Android4.0 隐藏虚拟按键的问题 实现全屏
- 隐藏虚拟按键的实现
- android虚拟按键的实现
- 自动化测试如何解决验证码的问题
- 自动化测试如何解决验证码的问题
- 自动化测试如何解决验证码的问题
- 自动化测试如何解决验证码的问题
- 自动化测试如何解决验证码的问题
- 自动化测试如何解决验证码的问题
- 【收集】解决自动化测试中那些难以实现的交互
- Python-Selenium2做Web自动化测试(6)-解决使用Webdrive打开Firefox不含有插件的问题
- Android 解决界面底部弹出dialog被虚拟按键遮挡一部分的问题
- 虚拟按键遮挡控件的问题
- Adapter(适配器)--类对象结构型模式
- 面试中的C++常见问题
- 2012年5月SAT香港真题解析
- 数据库语句之建表、拷贝数据表
- oc--alloc和 init,为什么init后内存地址变了
- 实现Python虚拟按键解决getch()的自动化测试问题
- 安卓错误解决
- Unity编译到Xcode自动添加AppIcon
- 《深度学习》学习笔记(一):稀疏自编码器(Sparse Autoencoder)
- linux下mysql的远程连接
- spring 自动装配autowire=byName或byType
- final修饰符的三种使用场景
- Android onClick和滑动事件冲突解决
- arcmap 报错 add field failed