【工作经历:阿里巴巴搜索技术研发中心QA ,百度新产品测试部QA】 【领域:测试分析,自动化测试,性能测试,安全测试 】 【个人定位:高级测试工程师+培训师+领域产品专家】

发布新日志

  • 拿到了离职申请表

    2008-08-13 14:49:39

    ÓãÓã¶àýÌåÈռDZ¾
    今天拿到离职申请表了。没有找到工作,就直接离职的。
    公司是做微软外包业务自动化的一个公司,公司还是挺不错的。虽说是IT企业排行榜,黑榜前5名之内的企业。
    最起码公司对我们部门还是很好的。工作环境很轻松。虽然没有任何的奖金和加班费。
    工作也很简单,微软中国发过来要自动化的case,我们负责把他自动化就可以了。使用微软的框架,写代码。
    前期工作还是很兴奋的。可以接触到微软内部的很多资源。趁这个机会,我弥补了很多的知识。
     
    后来发现,在公司,除了走管理,在测试上已经没有任何发展了。长期从事重复性的代码编写工作。甚至是让自己都忘记了测试的很多概念。和自己当初指定的目标已经偏离了。
    也想过做一些突破。想去写一些微软的maui,mita的扩展。但是被工作忙的几乎是没有时间。在公司又没有找到别人可以一起做一些研究。很多人都习惯了浅尝辄止和不求甚解。认真钻研技术的朋友不是太多。自己还要坚持学英语和其他技术,常常是每天一两点才睡觉。
     
    后来发现这样不行,即使自己再做一年,也不会有太大的发展。所以,打算换行去做自动化和性能测试。脱离微软系。争取在国内的公司里找到一个工作平台,然后用半年的时间去熟悉。用一年的时间成为专家。对于肯学习,肯努力的人来说,任何技术都不是问题。机会和积累才是最重要的。
     
    我在没有找工作的前提下,向公司提出了离职。我的朋友包括公司里的一些领导都不理解。即使我离职,他们也希望我可以继续在公司呆着直到找到新的工作职位。考虑到公司的工作交接上会有一些麻烦,所以,我在做完自己的项目后,就提出了离职。我不希望自己的离开会给公司带来什么影响。虽说对公司有不少的怨言,毕竟还是有感情的。
     
    总监的对我不太高兴,他是个资历很老的人。有魄力,雷厉风行。他一直反对员工的浮躁,反对跳槽。他和我的性格有点像。
    平时,我们也有过几次聊天,谈论工作和职业人生。我曾经是非常赞同他的。但是我现在的离开,或许会让他感到我这个人很虚伪和浮躁的。花了点时间,给几位领导写了一封比较长的邮件,向他们解释了我这个非常“不理智”的想法。希望可以得到他们的理解。
     
    很多员工走的时候,都对公司充满了怨言,有的人还在一些IT论坛上对公司破口大骂。我觉得,公司虽然有很多缺点,但是也没有必要把责任全部推卸给公司。
    的确阿里巴巴,华为,微软的工资就是高,但是,高薪是因为人家养的是人才,如果自认为是人才,可以去大公司试试。
    北京外包公司很多,对于一个普通的没有任何背景的公司来说,是不容易的。公司的工资水平是取决于公司的盈利状况的,盈利状况取决于项目的业绩。项目的业绩取决于项目组,项目组靠的是leader和每一个member。最终工资水平还是取决与个人的。
    虽然每个人都会收到上一波的公司员工的影响。但是机会是有的。公司是有舞台让每个人都有机会去完成自己的业绩的。
    公司烂,同时也表示了这个公司渴望有新人新秀出现。公司的人才流失,同样也可以让新人很快的得到更好的工作职位和项目。乐观看待就可以了。
    对于一个新人来说,这些条件已经是不错的了。
    我喜欢把公司的发展和盈利模式,比喻为食物链,有的是肉食,只肯最有营养的,块头大的项目。有的公司就是草食,只能小型的项目去吃。也有不少公司是有自己的产品,是耕种型的。并无绝对界限。我想我们不能只赞扬老虎,完全否定羚羊。公司也是多样性的。无论处在什么样的公司里,我们都应该把精力放在自己的事业上,而不是满腹怨言上。

    不过公司的工资的确是非常的低,北京行业里的最低工资。这份工资连找女朋友都没有自信。
     
    交接完所有的工作,剩下的就是手续了。我得以有时间去学习一些以前没有机会去学的东西。比如linux,selenium等,还有51testing上一些不错的文章和blog。
     
    我以前在51testing上看到过很多的招聘广告,发现只有阿里巴巴和搜狐的测试最专业。所以,就挑了这两个公司去面试。两个公司都已经参加过二次面试。不知道结果如何。我想只要努力了,就已经足够了。
  • 两场重要的面试

    2008-08-10 17:48:58

    面试花了一天的时间。
    上午是sohu,有点晚了,因为朋友的事情,迟到了半个小时。
    之前给sohu的工程师承诺过,两个星期熟悉qtp。实际上,自己只看了4天。之前项目有点忙。
    有点紧张。害怕自己过不了,这样容易让他们以为我是个喜欢吹嘘的人。
    去公司后,接到他们的面试题,14个小题,两个大题。
    做的时候,我的笔就没有中断过,一口气答完了所有的问题。有两三个问题,因为忘记函数名字了,直接如实回答了。不想浪费他们的时间。

    答完问题,然后就是面试,这次面试又是勉强,问了几个问题,我也不知道如何回答。比如使用qtp如何检测窗口里的对象在指定之间内有无变化,也就是如何实现快照功能。没有答好。还有如何检测控件的重叠问题。等等。
    这个问题,我会继续研究的。等想好了方法,给他联系。

    结果要等几天才可以出来,估计是奥运后了。


    下午接着赶去朝阳区的阿里巴巴。
    坐车就花了快两个小时了,真是远啊。
    到了他们的北京总部,在门口等了一会,因为约定是4点,我提前了一个小时。后来提前了45分钟给他们打电话了,他们有点意外,看来,以后一定要按照时间表来,毕竟别人也有事情安排。

    做了一个笔试题,不是太难,c#的一些问题,还有一个排序,两个智力题,还有sql的连接查询等。都答上了。
    后来面试,面试感觉不理想。说了很多。主要是说自己是偏技术型的,也希望可以在这个方向上发展。
    听到他们说,主要是在shell下测试,感觉还是挺好的。工作地点可能是杭州,无所谓了,事业要紧。
    等结果吧。

    sohu已经是第二面了,也是最后一面。
    阿里巴巴是第一面,被通知准备下一次面试。

    sohu面试的时候,遇到了一个面试开发的工程师。 就和他聊了一会。问他要求的工资是多少,他说是10k。
    我差点没有晕倒。他的实力很强。研究生,北理工的,熟悉linux编程。工作经验只有一年。当初校园招聘的时候,就直接是8k。现在终于看到差距了。
    当初面试的时候,感觉是国内的企业,可能资金不是太雄厚,况且自己也不是指瞪着工资看的人,就直接要了一个5k。和人家一比,真是汗颜。

    首先在国内争取到一个自动化或者性能测试的职位,然后专注一年,成为一个专家。稳定自己在行业里的地位。
    同时,成立一个测试专家组,交流技术。争取国内的一些大项目。

    微软外包业务,如果进入不了重要项目,或者不走管理,真的是没有太多发展空间。还是早早选择自己的路吧。






  • 个人技术能力发展方向定位

    2008-08-06 16:15:02

    定位一下自己的发展方向,每个栏目里的能力按优先级排序,以后想到什么,再更新。
    主要是明确自己的目标。不让自己学习的没有目的性。同时注重职业能力。
    这些技能是需要得到重点加强的。


    开发能力

    1、c++
    2、c#
    3、python
    4、汇编

    web技能
    1、javascrīpt & vbscrīpt & ajax
    2、asp.net & soap
    3、css &html & xml & xpath
    4、jsp

    os平台

    1、windows
    2、red hat linux
    3、ubuntu


    web应用服务器
    1、iis
    2、apache&tomcat
    3、weblogic&websphere

    数据库服务器
    1、ms sql server & t-sql
    2、oracle

    测试工具
    1、QTP
    2、Loadrunner
    3、微软的maui,mita和其他自动化测试技术。
    4、TD & QC
    5、selenium


    network技术

    1、数据嗅探(tcp,udp,http,soap,snmp)
    2、网络分析
    2、数据包分析、数据包修改


    办公处理

    1、word & excel & access 高级应用,会定义格式,定义函数


    沟通和管理
    1、沟通能力
    2、组织能力
    3、管理能力

    外语能力

    1、英语,要达到与外国人顺畅沟通的程度。专注此一样。

    hack能力

    1、注入
    2、跨站

  • 习惯了加班加点

    2008-08-05 21:43:59

    在公司工作的一年里,我有一半的时间在加班,公司没有要求,是自己申请加班的。好整理项目,学习知识。
    已经习惯了加班。一旦到周末,就感到非常空虚。只能翻看书。
    所以,平时特别不喜欢放假,一旦放假,就不能继续工作和学习了。
    我经常很奇怪,那些在公司一分钟也不多呆的同事。

    以前同学说我是工作狂,我当时以刚入职为由回复他。现在看看,的确是有点。
    不妨放松一下自己。

    以后的学习要提高效率,有的放矢,不要浪费太多的精力。
    现在是精英时代,唯有人才才可以真正的站稳脚跟,笑傲风云。
    有能力的人,是不会担心从业人员的多少的。

  • 能力事业为重

    2008-08-05 21:30:25

    离搜狐的面试还有两天,有点兴奋。

    感觉自己没有准备充分,qtp本身还没有太多实践,只是熟悉了一下,然后看看教程而已。qtp自身的英文帮助文档,估计是没有时间看了。不过还是要全面的浏览一下,不要遗漏什么。

    我找工作不是那种大面积撒网型。不喜欢四处投简历。我只要看好了一家企业,就会开始认真的对待,准备,投递简历,调整状态,然后等待面试。我不想浪费太多的精力去参加一些没有意义的面试。
    公司和人一样,都是有个性的。做事沉稳,有内涵,我喜欢这样的公司。

    首先我确定了自己的发展方向,自动化,性能,后台测试。
    手工测试也有很多的技术和要求,但是毕竟是可以迅速的掌握,容易培养后备,所以,以后也没有太大的前途,除非走上管理。
    微软系也很好,使用微软的自动化测试框架进行工作,这个很有前途,但是框架一旦确定下来,也没有太多的发展余地了,只能重复的去做体力劳动。当然突破口依然是有的,可惜现在内外交困,现在的公司工资太低,生活保障都是问题,不得不离开。同时,公司也一直奉行低端策略。一直无法留住有能力的人,人才大都流失,真的是替公司痛心。

    6k的工资去微软系,5k的工资去国内企业,我选择国内。
    能力和事业才是最重要的,只要饿不死,就坚持到底,一定要成为一个技术和管理都要强的人。

  • qtp自动化测试实践即将看完

    2008-08-05 20:34:19

    当初说好是两个星期熟悉的。结果项目忙,又有些事情,导致了这个星期才开始看。
    也就是说,我只有4天的时间去看。我的看不过是走马观花,看的很快。
    直接看重点。关键部分做了笔注。

    结果两天就看完了大部分,还剩下几章,明天就可以看完了。
    书写的不错。qtp的要点都介绍到了。感觉就是把自己多年的经验堆积到一起。实用,全面,效率也高。
    非常适合像我这样的新手。

    不过底层的原理介绍有点少,可能因为作者面向的对象是广大的测试人员,精通windows底层的人不多。才这么安排的。前面的关于ui机制和反射的部分,倒是让我收获不小。
    书中大篇幅的介绍了qtp的描述性编程,一些控件的使用,而且个个都有代码例子,对每个控件的介绍也就是一两个方法或者属性,由此可以看出,作者经验丰富,编程老到,而且是标准的技术型人才。书中关于测试流程,测试策略,测试文档,测试管理的部分相对较少,也可以印证此点。


    总的来说,这本书非常的不错,非常实用,测试人员不可或缺的一本书。

  • 小小的一个打击

    2008-08-05 20:23:27

    今天被打击了一次。

    阿里巴巴的人给我打电话,进行了一次简短的电话面试。
    问我linux的查看进程的命令是什么,真晕了,竟然忘记了。好像是list,或者ps。linux好久没有用,都差不多忘记了。这个周末一定装出一个虚拟机玩玩。熟悉一下,温习温习。
    她竟然还问我selenium,这个以前研究过,后来又放弃的东西。看来,在他们的项目中,是用的比较多的。即使不用,也是有过很深的研究。而我早就放弃了。

    熟悉了这么久的微软测试框架,一点也没有帮上我的忙。qtp也没有问。只是问基本能力。
    问我精通什么,我说c最擅长,她说c++会不会,无敌了。早知道,回答的就认真一点了。要知道
    c和c++是很大不同的。看来以后要说自己熟悉c++了。

    以后要慎重了。注重一点实际能力。把自己锻炼好。

    成为一个专家。


    阿里巴巴是我最向往的公司,要进就进这样有难度的,有技术的公司。这样才可以学习到真正的东西。
    才可以发挥自己的能力。

  • 以后专注于qtp和loadrunner

    2008-08-04 19:33:29

    今天发邮件有点厉害,和一个同事讨论问题发了十多封。最后终于解决。
    沟通和交流真的是有帮助,以后在公司一定要多问,多听。
    这是个非常宝贵的财富。

    问问题的过程,其实也是快速完成任务的过程。不保守,勤沟通,在工作中非常的重要。

    昨天的问题,终于解决。对maui的认识又重新进入了一个层次,现在已经可以无障碍的编程了。
    以前使用别人封装的框架,感觉没有调用底层方便。后来才发现,原来是各有优劣的。
    别人也是曾经付出过努力的。

    对web的dom机制理解更深了一个层次。大部分工具都是调用的mshtml的接口。

    最近要抓紧时间学习qtp,和搜狐的面试只有三天了。51testing出的那本书,还没有看一半,qtp自身的帮助还没有看。昨天想学习qtp那,结果qtp过期了。原来使用的破解工具没有用。
    看了一下,才发现那个工具是针对c盘安装目录进行配置的。真晕了。我没有装c盘。

    以后要专注与qtp和loadrunner了。能自己写的工具,也要依赖他们去完成,锻炼自己的能力。
    擅长和精通技能,是我的特长。编程能力不要太看重的,专注于工作。把工作做好,把职业技能锻炼好,这才是最重要的。看到论坛上那么多人招收测试工程师,高手却很少。真的是遗憾。
    软件测试的这些东西,没有太难的东西,阿里巴巴的那些容量扩充问题除外,都是工具的使用,脱离了工具,我也可以搞定。所以,熟悉工具是非常紧急的。

    定好了方向,努力吧,让自己成为牛人。









  • 一些需要继续研究的小疑问

    2008-08-03 23:03:38

    几个小问题,下星期上班后继续反编译代码研究。

    1、如何使用maui进行web自动化。
    平时使用的东西,都是封装好了的。想看看最原始的代码是什么样的。熟悉一下流程。平时的例子也都是winform的。
    2、maui捕获ie的原理是什么。
    难道也是使用dom机制,从一个窗口中抓到dom。然后解析。
  • Reflector .net程序反编译工具的一些插件

    2008-08-01 19:06:25

    Reflector.FileDisassembler
    This add-in can be used to dump the disassembler output to files for any Reflector supported language.
    Website Download

     

    Reflector.CodeMetrics
    Analyses .NET assemblies and shows design quality metrics. The menu item is registered under the "Tools" menu.
    Website Download

     

    Reflector.SQL2005Browser
    This add-in allows to browse .NET assemblies stored in SQL Server 2005 (Yukon) databases.
    Website Download

     

    Reflector.DelphiLanguage
    The Delphi view that is used inside .NET Reflector provided as a language add-in.
    Website Download

     

    Reflector.McppLanguage
    This add-in extends Reflector with a Managed C++ language rendering module.
    Website Download

     

    Reflector.ChromeLanguage
    This add-in extends Reflector with a Chrome language rendering module.
    Website Download

     

    Reflector.Diff
    This add-in shows differences between two versions of the same assembly.
    Website Download

     

    Reflector.VisualStudio
    This program is hosting .NET Reflector inside the Visual Studio 2003 IDE. Run Reflector.VisualStudio.exe to register the add-in with Visual Studio.
    Website Download

     

    Reflector.ClassView
    Shows class definitions as plain text with color coding. The menu item is registered under the "Tools" menu.
    Website Download

     

    Reflector.CodeModelView
    This add-in shows the underlying code model objects for a selected node in .NET Reflector. The menu item is registered under the "Tools" menu.
    Website Download

     

    Reflector.FileGenerator
    This add-in can be used to dump the disassembler output to files for any Reflector supported language.
    Download

     

    Reflector.Graph
    This add-in draws assembly dependency graphs and IL graphs.
    Website Download

     

    Reflector.OpenRunningAssembly
    Opens an assembly or dependency from a process running on the system. The menu item is registered under the "Tools" menu.
    Website Download
  • web自动化初步探索

    2008-08-01 16:35:09

    这是关于mshtml的资料。msdn上的。以后会经常遇到。
    http://msdn.microsoft.com/en-us/library/aa752616(VS.85).aspx

    今天又重新反编译了maui的代码,看看它的html功能是如何实现的。
    基本功能是调用mshtml的接口。然后就去msdn上搜索资料去了。
    少数功能是调用一些非mshtml.dll文件以外的api。估计也是和mshtml的体系有关的。

    对于这些底层的东西,一定要弄透彻。
    对mshtml这个文件还不是太熟悉。需要熟悉一下。
  • 操纵遨游工具栏的方法,解决spy++无法捕获控件的问题(2)

    2008-07-31 17:48:06

    利用微软内部工具 mitaspy可以发现msaa对象。这说明,mita比maui要强。mita也是微软以后的标准。

    同时发现了FindWindowEx只能搜索子窗口,不能搜索孙子窗口,所以,需要提前注意窗口的嵌套层次。
    这个问题完结了。我也不研究了。继续其他的学习。

    更新后的代码


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using Accessibility;

    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                int hWnd = FindWindowEx(0, 0, "Maxthon2_Frame", null);
                int sub = FindWindowEx(hWnd, 0, "XTPDockBar", null);
                int subhwnd = FindWindowEx(sub, 0, null, "标准工具栏");
                if (subhwnd!= null)
                    Console.WriteLine("OK, Found the toolbar");
                msaa((IntPtr)subhwnd);

                Console.ReadKey();
            }

            [DllImport("oleacc", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
            public static extern int AccessibleChildren(IAccessible paccContainer, int iChildStart, int cChildren, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] object[] rgvarChildren, ref int pcObtained);

            [DllImport("oleacc.dll")]
            internal static extern int AccessibleObjectFromWindow(
                          IntPtr hwnd,
                          uint id,
                          ref Guid iid,
                          [In, Out, MarshalAs(UnmanagedType.IUnknown)] ref object ppvObject);

            internal enum OBJID : uint
            {
                WINDOW = 0x00000000,
                SYSMENU = 0xFFFFFFFF,
                TITLEBAR = 0xFFFFFFFE,
                MENU = 0xFFFFFFFD,
                CLIENT = 0xFFFFFFFC,
                VSCROLL = 0xFFFFFFFB,
                HSCROLL = 0xFFFFFFFA,
                SIZEGRIP = 0xFFFFFFF9,
                CARET = 0xFFFFFFF8,
                CURSOR = 0xFFFFFFF7,
                ALERT = 0xFFFFFFF6,
                SOUND = 0xFFFFFFF5,
            }

            [DllImport("user32.dll")]
            public static extern int FindWindowEx(int hwndParent, int hwndChildAfter,
                string lpszClass, string lpszWindow);

            public static void msaa(IntPtr hwnd2)
            {
                object ōbj = new object();
                Guid guid = new Guid("{618736E0-3C3D-11CF-810C-00AA00389B71}");
                AccessibleObjectFromWindow(hwnd2, (uint)OBJID.WINDOW, ref guid, ref obj);
                IAccessible accessible = obj as IAccessible;
                accessible = accessible as IAccessible;
                Object[] childs = new Object[accessible.accChildCount];
                int ōbtained = 0;
                try
                {
                    AccessibleChildren(accessible, 0, accessible.accChildCount, childs, ref obtained);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                Console.WriteLine(accessible.accChildCount);
                Console.WriteLine(obtained.ToString());

                for (int i = 0; i < obtained; i++)
                {
                    IAccessible child = childs[i] as IAccessible;
                    Console.WriteLine(child.get_accName(0));                
                    Object[] accchilds = new Object[child.accChildCount];
                    int result = 0;
                    AccessibleChildren(child, 0, child.accChildCount , accchilds, ref result);
                    for (int j = 0; j < result; j++)
                    {
                        IAccessible jchild = accchilds[j] as IAccessible;
                        Console.WriteLine(jchild.get_accName(0));     
                    }
                }
            }
        }
    }





  • 操纵遨游工具栏的方法,解决spy++无法捕获控件的问题

    2008-07-31 17:03:41

    这个问题,相信很多从事自动化测试的人都会遇到。

    我初步想到的两个方法。经过实践已经可以了。
    这个问题算是可以放下了。
    以后开始主攻qtp。

    1、利用位置。工具栏的整个子窗口的绝对位置是可以得到的。里面的按钮大小都是相差无几的。所以,可以计算出里面的每个按钮的大体位置,发送一个点击消息,填充消息内容就可以了。


    2、利用msaa机制。
    利用标题,定位到遨游浏览器,以为工具栏的类名和其他控件的类名一样,所以,不能单独的通过FindWindowEx 来找到子窗口的句柄。(即使提供了标题参数,依然是定位不到,这个很奇怪,我没有深究,可能其他的api可以搞定)(搜索了一下资料,才发现原来中间还有窗口嵌套,FindWindowEx只能搜索子结点,不能搜索孙子节点)。我采用了EnumChildWindows函数。遍历里面的子窗体,根据属性判断出工具栏的窗体句柄。然后利用msaa的api得到msaa对象。枚举他的孩子对象,就可以得到所有的按钮的msaa对象了。

    然后利用msaa的机制,就可以操纵工具栏了。

    发送消息请参考
    http://www.cnblogs.com/karoc/archive/2006/11/29/576253.aspx



    以下是查找的关键代码。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using Accessibility;

    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                int hWnd = FindWindowEx(0, 0, "Maxthon2_Frame", null);
                EnumChildWindows(hWnd, callBackEnumChildWindows, 0);
                Console.ReadKey();
            }

            [DllImport("oleacc", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
            public static extern int AccessibleChildren(IAccessible paccContainer, int iChildStart, int cChildren, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] object[] rgvarChildren, ref int pcObtained);

            [DllImport("oleacc.dll")]
            internal static extern int AccessibleObjectFromWindow(
                          IntPtr hwnd,
                          uint id,
                          ref Guid iid,
                          [In, Out, MarshalAs(UnmanagedType.IUnknown)] ref object ppvObject);

            internal enum OBJID : uint
            {
                WINDOW = 0x00000000,
                SYSMENU = 0xFFFFFFFF,
                TITLEBAR = 0xFFFFFFFE,
                MENU = 0xFFFFFFFD,
                CLIENT = 0xFFFFFFFC,
                VSCROLL = 0xFFFFFFFB,
                HSCROLL = 0xFFFFFFFA,
                SIZEGRIP = 0xFFFFFFF9,
                CARET = 0xFFFFFFF8,
                CURSOR = 0xFFFFFFF7,
                ALERT = 0xFFFFFFF6,
                SOUND = 0xFFFFFFF5,
            }

            /// <summary>
            /// //////////////////////////////////
            [DllImport("user32.dll")]
            public static extern int FindWindowEx(int hwndParent, int hwndChildAfter,
                                                                               string lpszClass, string lpszWindow);
            [DllImport("user32.dll")]
            public static extern int GetWindowText(int hWnd, StringBuilder lpString, int nMaxCount);

            [DllImport("user32.dll")]
            public static extern int EnumChildWindows(int hWndParent, CallBack lpfn, int lParam);

            /// <summary>
            /// 回调函数代理
            /// </summary>
            public delegate bool CallBack(int hwnd, int lParam);

            /// <summary>
            /// 子窗口回调处理函数
            /// </summary>
            /// <param name="hwnd"></param>
            /// <param name="lParam"></param>
            /// <returns></returns>
            public static bool ChildWindowProcess(int hwnd, int lParam)
            {
                StringBuilder title = new StringBuilder(200);
                int len;
                len = GetWindowText(hwnd, title, 200);
                if (len < 1)
                    return true;
                if (title.ToString().Contains("标准工具栏"))
                {
                    Console.WriteLine("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
                    msaa((IntPtr)hwnd);
                    Console.WriteLine("ddddddddddddddddddddddddddddddddddddddddddddddddddddddddd");
                }
                Console.WriteLine(title + " " + hwnd);
                return true;
            }

            /// <summary>
            /// 子窗口回调函数代理
            /// </summary>
            public static CallBack callBackEnumChildWindows = new CallBack(ChildWindowProcess);

            public static void msaa(IntPtr hwnd2)
            {
                object ōbj = new object();
                Guid guid = new Guid("{618736E0-3C3D-11CF-810C-00AA00389B71}");
                AccessibleObjectFromWindow(hwnd2, (uint)OBJID.WINDOW, ref guid, ref obj);
                IAccessible accessible = obj as IAccessible;
                accessible = accessible as IAccessible;
                Object[] childs = new Object[accessible.accChildCount];
                int ōbtained = 0;
                try
                {
                    AccessibleChildren(accessible, 0, accessible.accChildCount, childs, ref obtained);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                Console.WriteLine(accessible.accChildCount);
                Console.WriteLine(obtained.ToString());

                for (int i = 0; i < obtained; i++)
                {
                    IAccessible child = childs[i] as IAccessible;
                    Console.WriteLine(child.get_accName(0));               
                    Object[] accchilds = new Object[child.accChildCount];
                    int result = 0;
                    AccessibleChildren(child, 0, child.accChildCount - 1, accchilds, ref result);
                    for (int j = 0; j < result; j++)
                    {
                        IAccessible jchild = accchilds[j] as IAccessible;
                        Console.WriteLine(jchild.get_accName(0));                    
                    }
                }
            }
        }
    }




  • MSAA 开发SDK

    2008-07-30 20:50:24

    http://www.microsoft.com/downloads/details.aspx?displaylang=en&familyid=4179742f-1f3d-4115-a8ba-2f7a6022b533

    这个SDK里所带的几个inspect object的工具还是不错的。


    下面是msaa的官方介绍
    http://msdn.microsoft.com/en-us/library/ms697707.aspx


    无意中,竟然发现国外一个比较不错的测试网站
    http://www.sqaforums.com/ubbthreads.php


    firefox官方竟然也有讨论
    http://www.mozilla.org/access/windows/msaa-server

    奇怪的是,我写的代码,竟然无法不能找到遨游的标准工具栏。真是奇怪。其他的就可以了。

           public static void msaa()
            {
                object ōbj = new object();
                IntPtr hWnd = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "Maxthon2_Frame", null);
                IntPtr hwnd2 = FindWindowEx(hWnd, IntPtr.Zero, "XTPToolBar", "标准工具栏");
                Guid guid = new Guid("{618736E0-3C3D-11CF-810C-00AA00389B71}");

                AccessibleObjectFromWindow(hwnd2, (uint)OBJID.WINDOW, ref guid, ref obj);
                IAccessible accessible = obj as IAccessible;
                Object[] childs = new Object[accessible.accChildCount];
                int ōbtained = 0;
                AccessibleChildren(accessible, 0, accessible.accChildCount - 1, childs, out obtained);

                Console.WriteLine(obtained.ToString());


                for (int i = 0; i < obtained; i++)
                {
                    IAccessible child = childs[i] as IAccessible;
                    try { Console.WriteLine(child.get_accName(0)); }
                    catch { }
                    Object[] accchilds = new Object[child.accChildCount];
                    int result = 0;
                    AccessibleChildren(child, 0, child.accChildCount - 1, accchilds, out result);
                    for (int j = 0; j < result; j++)
                    {
                        IAccessible jchild = accchilds[j] as IAccessible;
                        try { Console.WriteLine(jchild.get_accName(0)); }
                        catch { }
                    }

                }
                Console.ReadLine();

            }

  • c#反射机制和一个简单的例子

    2008-07-30 19:29:15

    上次搜狐的面试人员问我自动化测试里反射的应用。我当时不知道反射机制的具体应用。
    回头看了一下,才终于明白了反射的定义。以前只知道是rename和得到当前的方法。
    没有想到,竟然可以执行自动化操作。怪不得他们问我了。

    研究了一下msdn。然后从里面提取了一个不错的小例子。对于理解反射非常有帮助。




    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Reflection;

    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                test1();
                Console.ReadKey();
            }
            public static void test1()
            {
                // Loads an assembly using its file name.
                Assembly a = Assembly.LoadFrom(@"F:\Documents and Settings\v-yahuan\Desktop\ttt\TestRun0501\WinApp\bin\Debug\WinApp.exe");
                // Gets the type names from the assembly.
                Type[] types2 = a.GetTypes();
                foreach (Type t in types2)
                {
                    Console.WriteLine(t.FullName);
                    foreach (MemberInfo m in t.GetMethods())
                    {
                        Console.WriteLine("methods " + m.Name);
                    }
                }
                Console.WriteLine();
            }


            public static void test2()
            {

                Type t = typeof(ConsoleApplication1.Program);
               
                Console.WriteLine("Listing all the members (public and non public) of the {0} type", t);

                // Lists static fields first.
                FieldInfo[] fi = t.GetFields(BindingFlags.Static |
                 BindingFlags.NonPublic | BindingFlags.Public);
                Console.WriteLine("// Static Fields");
                PrintMembers(fi);

                // Static properties.
                PropertyInfo[] pi = t.GetProperties(BindingFlags.Static |
                 BindingFlags.NonPublic | BindingFlags.Public);
                Console.WriteLine("// Static Properties");
                PrintMembers(pi);

                // Static events.
                EventInfo[] ei = t.GetEvents(BindingFlags.Static |
                 BindingFlags.NonPublic | BindingFlags.Public);
                Console.WriteLine("// Static Events");
                PrintMembers(ei);

                // Static methods.
                MethodInfo[] mi = t.GetMethods(BindingFlags.Static |
                 BindingFlags.NonPublic | BindingFlags.Public);
                Console.WriteLine("// Static Methods");
                PrintMembers(mi);

                // Constructors.
                ConstructorInfo[] ci = t.GetConstructors(BindingFlags.Instance |
                 BindingFlags.NonPublic | BindingFlags.Public);
                Console.WriteLine("// Constructors");
                PrintMembers(ci);

                // Instance fields.
                fi = t.GetFields(BindingFlags.Instance | BindingFlags.NonPublic |
                 BindingFlags.Public);
                Console.WriteLine("// Instance Fields");
                PrintMembers(fi);

                // Instance properites.
                pi = t.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic |
                 BindingFlags.Public);
                Console.WriteLine("// Instance Properties");
                PrintMembers(pi);

                // Instance events.
                ei = t.GetEvents(BindingFlags.Instance | BindingFlags.NonPublic |
                 BindingFlags.Public);
                Console.WriteLine("// Instance Events");
                PrintMembers(ei);

                // Instance methods.
                mi = t.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic
                 | BindingFlags.Public);
                Console.WriteLine("// Instance Methods");
                PrintMembers(mi);

                Console.WriteLine("\r\nPress ENTER to exit.");
                Console.Read();
            }

            public static void PrintMembers(MemberInfo[] ms)
            {
                foreach (MemberInfo m in ms)
                {
                    Console.WriteLine("{0}{1}", "     ", m);
                }
                Console.WriteLine();

            }
        }
    }


  • 遍历一个窗口的子窗口代码

    2008-07-25 21:30:59


    从网上搜索到一段代码。我使用它来验证我的一个思想。
    spy++肯定是根据hwnd来遍历的。如果一个控件不能被spy++识别。就只能通过msaa来识别。
    这样是说hwnd和msaa并不是一一对应。疑问?

    这个代码是无法遍历到遨游的工具栏的。
    我使用msaa是可以的。

    同时也可以使用消息,通过spy++获取发送的消息,然后模拟就可以了。
    鼠标点击的位置是可以通过他们的父控件的位置来计算出来的。

    再想,也许可以有其他的方法。


           static void Main(string[] args)
            {
                //IsClientPopupWindows();
                EnumChildWindows(920262, callBackEnumChildWindows, 0);
                Console.ReadKey();
            }


            [DllImport("user32.dll")]
            public static extern int FindWindowEx(int hwndParent, int hwndChildAfter,
                                                                               string lpszClass, string lpszWindow);

            [DllImport("user32.dll")]
            public static extern int FindWindow(string strclassName, string strWindowName);


            [DllImport("user32.dll")]
            public static extern int GetLastActivePopup(int hWnd);

            [DllImport("user32.dll")]
            public static extern int AnyPopup();

            [DllImport("user32.dll")]
            public static extern int GetWindowText(int hWnd, StringBuilder lpString, int nMaxCount);

            [DllImport("user32.dll")]
            public static extern int EnumThreadWindows(int dwThreadId, CallBack lpfn, int lParam);

            [DllImport("user32.dll")]
            public static extern int EnumWindows(CallBack lpfn, int lParam);

            [DllImport("user32.dll")]
            public static extern int EnumChildWindows(int hWndParent, CallBack lpfn, int lParam);

            /// <summary>
            /// 回调函数代理
            /// </summary>
            public delegate bool CallBack(int hwnd, int lParam);


            /// <summary>
            /// 进程回调处理函数
            /// </summary>
            /// <param name="hwnd"></param>
            /// <param name="lParam"></param>
            /// <returns></returns>
            public static bool ThreadWindowProcess(int hwnd, int lParam)
            {
                EnumChildWindows(hwnd, callBackEnumChildWindows, 0);
                return true;
            }

            /// <summary>
            /// 窗口回调处理函数
            /// </summary>
            /// <param name="hwnd"></param>
            /// <param name="lParam"></param>
            /// <returns></returns>
            public static bool WindowProcess(int hwnd, int lParam)
            {
                EnumChildWindows(hwnd, callBackEnumChildWindows, 0);
                return true;
            }

            /// <summary>
            /// 子窗口回调处理函数
            /// </summary>
            /// <param name="hwnd"></param>
            /// <param name="lParam"></param>
            /// <returns></returns>
            public static bool ChildWindowProcess(int hwnd, int lParam)
            {
                StringBuilder title = new StringBuilder(200);
                int len;
                len = GetWindowText(hwnd, title, 200);
                if (len < 1)
                    return true;
                if(title.ToString().Contains("标准工具栏"))
                    EnumChildWindows(hwnd, callBackEnumChildWindows, 0);
                Console.WriteLine(title+" "+hwnd);
                return true;
            }


            /// <summary>
            /// 进程窗口回调函数代理
            /// </summary>
            public static CallBack callBackEnumThreadWindows = new CallBack(ThreadWindowProcess);

            /// <summary>
            /// 窗口回调函数代理
            /// </summary>
            public static CallBack callBackEnumWindows = new CallBack(WindowProcess);


            /// <summary>
            /// 子窗口回调函数代理
            /// </summary>
            public static CallBack callBackEnumChildWindows = new CallBack(ChildWindowProcess);

            /// <summary>
            /// 客户端是否弹出对话框
            /// </summary>
            /// <returns></returns>
            public static bool IsClientPopupWindows()
            {
                bool FindError = false;
                EnumWindows(callBackEnumWindows, 0);
                return FindError;
            }
  • 搜狐面试归来

    2008-07-25 20:51:44

    留意软件测试行业里的招聘广告有一段时间了。
    我一直试图通过这些招聘信息揣测这些公司的技术高低,侧重点,业务方向。甚至是未来的发展趋势。

    最后发现国内的公司中,搜狐和阿里巴巴的招聘信息里,对测试把握的最好。尤其是搜狐,分类很详细。
    同时因为他们有自己的搜索平台,技术也应该是不错的。然后就投递了一份简历。

    我投递了自动化测试。我想会有一些qtp之类的题目。等到了他们的公司,拿到面试题。却发现只有qtp。有点失望。如果只是考察qtp,我真的是没有希望。因为我对qtp接触比较少。

    然后就叫来了hr的同志,让他们换一份系统测试的题目。那一刻我有点迷茫。自动化,手工。忽然发现如此遥远与陌生。结果他给了我两个选择,要么是去面试高级自动化,如果我对测试工具的原理比较熟悉。要么去做手工测试。思考了一下,我决定冒险一下。选择了自动化。我不想放弃自动化测试这个方向。

    然后就是请来了技术工程师,跟我单独谈。问了好多问题。牵扯到系统底层和测试工具原理的一些东西。
    当初曾经对那些部分有过关注,只是感兴趣而已,略有关注。回答的很勉强。感觉很乱,不成系统,这说明我还没有对这些知识有个系统的理解。

    最后心血来潮,竟然给他打了一个赌。

    我会在两个星期之内熟悉qtp,然后再去做他们的笔试题。
    只是为了证明自己具有很强的学习能力。
    这个能力也是我非常看重的。
    他们也给我留了一个题。不过这个问题,在我回去之后,当天晚上就解决了。
    剩下的时间就是冲刺qtp了。

    我一直要求自己沉稳,这次竟然会和别人打赌,真是有点过头了。
    不过,我没有丝毫担心。

    两个星期,easy。



  • 反编译maui

    2008-07-25 20:34:09

    maui是微软的一套测试框架。我们的项目使用的是基于它之上的一个框架。很多最终的操作还是要靠maui实现。今天突然想看看他的原理,就开始了我的反编译之旅。

    幸好maui是不加密的。解密没有任何困难。代码也很清晰。
    从它的对象初始化开始跟踪它的对象识别体系。
    从它的操作功能跟踪他的对象操纵机制。

    需要留意的是window的识别,甚至是msaa都是根据api来获得的。window和msaa是使用的不同的api。
    这表明这两个对象是基于不同的机制。

    最终终于跟到了最后,所有的功能都是根据系统api和windows的消息机制来模拟的。web控件的识别和操作是基于mshtml的。

    平时调试程序的时候多有不变。模拟鼠标和键盘的操作,自然也会对调试者形成干扰。大部分情况还是使用日志进行分析。
    感觉如果加入一个驱动处理层就可以了。

    比如调试者的计算机为客户端,被操纵的计算机为服务端。客户端将命令发送到服务端的特定的管道。
    比如文件,数据库,网络socket。服务端通过一个处于驱动处理层的程序,将所有的命令翻译为api和消息进行执行。这样就可以一台计算机上控制多台计算机进行case执行。

    总共加班了6个小时,终于有了初步的认识。
    对于以后解决问题,会有一些帮助。




  • 《软件评测师教程》一书收到

    2008-07-14 17:20:32

    《软件评测师》这本书是在书店偶尔看见的,但是发现里面的知识很基础,也很全面。
    本来,作为一名测试工程师,对这种业界外的考试是不屑一顾的。但是看完那本清华大学出版的《软件评测师教程》后,发现真的很好。能够写出这样详细的书,真的是不容易啊。

    以前老是在卓越上买书,现在卓越提价了,超过90元才可以送货上门。当当的价格还是更低些。30元就可以了。
    理所当然就选择当当了。另外发现当当的书很全,比卓越的书多很多。

    虽然不考,但是这本书还是非常有用的。
  • Team Foundation与虚拟机

    2008-05-09 14:17:51

    公司里的vstf交给我管理了。
    公司的VSTF是建立在虚拟机上,这是为了方便数据的备份和转移。虚拟机不是采用的VM。而是微软的VPC。
    毕竟,在微软的网络里,使用微软的产品是比较恰当的。最起码,不需要花钱注册。
    我将一个虚拟机的文件copy到另一台计算机上,然后重新假设了一个虚拟机重新运行。本来打算想去认真的研究一下。但是发现会和原来的虚拟机冲突。
    这个冲突是无形的,因为一旦两个相同备份的虚拟机同时运行。后启动的虚拟机总会“抢掉”原来的虚拟机。
    两个虚拟机竟然会公用同一个ip。真是奇怪。修改了计算机名字也不行。
    两个装有vstf的虚拟机如果同时打开的话,就会报错。有意思。
    最近开始熟悉sharepoint,vstf。对这些新东西,真的是有点了解不多。





1728/9<123456789>
Open Toolbar