
1. 真题结构复盘小米测开笔试到底在筛什么人1.1 试卷题型与时间分配先说说整体印象。小米2020校招测试开发这套笔试题卷子结构其实非常典型选择题单选多选、简答题、算法编程题偶尔还夹杂一两道场景设计题。整套卷子限时大概90分钟到120分钟题量不算少尤其是选择题部分特别占时间。我当时拿到卷子的第一反应是这不像是在考“你会不会测”更像是在考“你有没有开发的底子”。为什么这么说因为整套卷子里的纯测试理论题占比并不高反而Java基础、数据结构和算法、数据库、还有Linux命令这些偏开发向的内容占了很大比重。后来我在小米工作一段时间后再回头看这套题发现这个出题逻辑其实非常合理测试开发在小米的业务场景里更多是跟Android系统、MIUI的各个模块打交道要能看懂代码、写自动化脚本、做性能定位没有扎实的开发基础根本玩不转。所以如果你正准备测开校招可以先做一个心理建设笔试阶段不会太偏重“怎么设计测试用例”这种功能测试题反而会重点考察你的代码能力、计算机基础功底。这不是说测试理论不重要而是笔试阶段要先筛掉一批代码不过关的人测试设计能力更多留在面试环节再考察。时间分配上我个人建议是选择题控制在40分钟以内简答题20到25分钟剩下至少30分钟留给编程题。编程题通常不是一道超级难的算法题而是中等偏下难度的题目但你要是被前面的选择题拖住最后编程题连题都读不完就非常可惜。我见过不少同学前面慢慢磨后面编程题直接空着这种丢分方式最痛。1.2 从出题看岗位能力模型复盘这套题你能清楚地看到小米测开岗位的三个能力支柱。第一是代码功底。选择题里会大量出现Java语法、集合框架、异常处理、多线程相关的题编程题更是直接考手写代码。这一块的目标是确认你能独立写代码而不是只能看别人写。第二是计算机基础知识。操作系统、计算机网络、数据库这些科目都会涉及但考得不深不会让你手写红黑树或者TCP拥塞控制的完整流程更多是考察你是否掌握常见概念。比如进程和线程的区别、TCP和UDP的应用场景、SQL的基本增删改查等。这部分考察的本质是你有没有完整的计算机知识体系遇到问题时能不能调用底层知识来辅助定位。第三才是测试素养。这一块会通过简答题来考比如“给你一个登录页面你怎么设计测试用例”“一条缺陷记录应该包含哪些要素”之类。这类题没有标准答案但能反映出你是有实战经验还是只会背书。我建议准备时按这个权重来分配精力开发基础60%计算机基础20%测试理论20%。很多科班出身的同学容易在测试理论上花太多时间背概念结果选择题反而被Java的细节点打得措手不及这属于备考方向跑偏了。2. 核心考点拆解数据结构和Java基础是硬门槛2.1 链表与字符串算法题的高频区选择题和编程题里数据结构的比重很突出尤其是链表和字符串这两个方向。为什么考这两个因为Android开发里到处是链表、队列、字符串处理而且这两个类型既能考基础操作又能延伸出算法复杂度的问题性价比很高。链表这块的经典考法有几种反转链表、判断链表是否有环、合并两个有序链表、删除倒数第N个节点。看起来都是LeetCode上的简单到中等题但笔试里的难点在于你不仅要写出来还要考虑边界条件。比如反转链表很多人只记得三指针法但笔试环境往往没有IDE提示纯手写很容易把指针的先后顺序弄错。我之前的做法是链表题一定要在纸上画一遍指针变化的过程不要上来就写代码。画清楚了代码基本就不会错。反转链表的本质就三句话保存下一个节点、把当前节点指向前一个节点、移动前一个和当前指针。你把这个过程在纸上画两遍闭着眼都能写出来。字符串的考法就更灵活了。常见的有字符串反转、判断回文、统计字符出现次数、字符串去重、最长公共前缀。这些题本身不难但要注意Java里String是不可变的很多操作会产生新对象如果循环里频繁拼接性能会很差。笔试里虽然不太会卡你性能但如果你能主动用StringBuilder而不是String String这个细节会被面试官注意到印象分会不一样。2.2 Java并发与集合考点背后是Android业务选择题里Java基础占了相当比例其中集合类和多线程是最常考的两个方向。集合类里ArrayList和LinkedList的区别、HashMap的底层结构、HashSet的去重原理、ConcurrentHashMap的线程安全机制基本是每年必考。举一个经典例子HashMap和Hashtable的区别。很多人能答出来“HashMap非线程安全Hashtable线程安全”但这只是第一层。真正的考点在于HashMap允许null键和null值Hashtable不允许HashMap的初始容量是16Hashtable是11HashMap扩容是原容量乘以2Hashtable是乘以2加1。这些细节你在项目里不一定用得上但笔试就是会考。我建议你把这些高频细节整理成表格来记比单纯刷题效率高很多。比如下面这种对比维度HashMapHashtable线程安全否是null键/值允许不允许初始容量1611扩容方式容量x2容量x21多线程这块常考的知识点包括synchronized和ReentrantLock的区别、volatile关键字的作用、线程池的参数含义、死锁的四个条件。这些知识点在Android开发里都有实际对应的场景。比如volatile为什么不能保证原子性其实去写一个多线程自增的例子就能理解线程池的corePoolSize和maximumPoolSize的区别你只要想过“为什么不能一上来就创建很多线程”这个问题就能想明白。回顾小米的这种出题风格你会发现它不是纯粹考Java语言本身而是把Java的知识点往业务场景上靠。比如synchronized和Lock的区别在Android里就对应着UI线程和子线程的同步问题。所以备考时不要死记硬背知识点多想一步“这个知识点在Android里会怎么用”笔试选择题的正确率会高很多。2.3 手写单例模式看似简单坑却不少编程题里经常出一个看起来很“简单”的题手写单例模式。别小看这道题它考察的东西非常多你对线程安全的理解、对volatile的使用、对类加载机制的认识甚至还包括你的代码风格。我见过很多同学写懒汉式单例直接就是public class Singleton { private static Singleton instance; public static Singleton getInstance() { if (instance null) { instance new Singleton(); } return instance; } }这样写在线程环境下会出问题两个线程可能同时进入if判断然后创建出两个实例。笔试里如果你只写出这个版本大概率只能拿一半分因为考官会追问你的代码是否线程安全。更合适的版本是双重检查锁DCLpublic class Singleton { private static volatile Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance null) { synchronized (Singleton.class) { if (instance null) { instance new Singleton(); } } } return instance; } }这个版本里volatile关键字不是可有可无的它主要是为了防止指令重排序导致拿到一个“半初始化”的对象。这个问题在很多面试八股文里都有但笔试里能写出来的人确实不多。其实单例模式在Android开发里太常见了系统服务、数据库Helper、网络请求客户端基本都会用单例来封装。这个题答好了考官会认为你有实际开发经验而不是纯应试选手。我建议你把饿汉式、懒汉式、双重检查锁、静态内部类这四种写法都练熟能说清楚各自的优缺点这道题基本就能拿满分。3. 测试设计题从“会点功能测试”到“懂测试设计”3.1 登录模块测试用例设计一道没有标准答案的题简答题里出现概率最高的一道是请设计登录功能的测试用例。这道题看起来简单因为所有人都能写出几条但真正拉开差距的是你能否写出“非功能”方向的用例。一般功能方向的用例大家都会写输入正确的用户名密码能登录成功、密码错误提示密码错误、用户名不存在提示用户不存在、点登录按钮无响应怎么办之类。这些能拿到基础分但拿不到高分。高分答案一定要有测试类型分层意识。我的习惯是把测试用例分成几类来写第一类功能测试。覆盖正常登录流程、记住密码、忘记密码、自动登录、退出登录这些主流程。第二类界面测试。检查登录页面布局是否正常、密码是否密文显示、错误提示是否友好、输入框的长度限制是否正确。比如密码框如果允许输入128位但你只输入100位就卡住了这也算界面问题。第三类兼容性测试。不同分辨率屏幕下的显示效果、不同Android版本的兼容性、不同网络环境WiFi、4G、弱网下的登录响应。第四类安全测试。SQL注入、密码是否明文传输、登录接口是否有频率限制、是否支持验证码、连续输错密码是否有锁定机制。第五类异常场景。用户登录时断网、服务端返回超时、账号在其他设备登录被踢下线、登录状态失效后点击需要登录的页面的处理。这样分类写出来的答案哪怕用例条数不多但结构清晰能反映出你具备测试设计的系统性思维。考官最怕看到的是东一句西一句地随便列几条这种答案很难给高分。3.2 缺陷报告要素你的Bug描述能让开发秒懂吗简答题里还有一类常考的是缺陷管理比如“一条完整的Bug记录应该包含哪些要素”或者“如何描述一个高质量的Bug”。这类题在很多人看来是送分题但真的拿满分的不多。一条合格的Bug记录至少要包含这么几项缺陷编号、所属模块、缺陷标题、操作步骤、实际结果、预期结果、严重级别、优先级、操作系统与机型、日志或截图。这些是最基本的你哪怕没实战经验背也背得下来。关键问题在于笔试可能会给你一个具体的Bug描述让你找出哪里写得不好。比如“用户点击登录按钮后APP闪退了。”这个描述的问题在哪里没有操作步骤、没有机型信息、没有复现概率、没有日志。这种描述开发拿到手根本没法定位问题。高质量的描述应该是这样的“在小米10 Android 12版本上登录页点击登录按钮输入正确账号和密码后点击确认APP立即闪退。必现。已抓取logcat日志见附件崩溃点位于LoginActivity的onClick方法中NPE异常。”这个描述里有机型、有步骤、有现象、有概率、有日志定位开发拿到手可以直接开始查代码。我还想多分享一个经验描述Bug时不要只写“怎么了”要写“怎么才能复现”。复现步骤写得越清晰开发排查的效率越高。测试和开发的关系其实是一门沟通学你的Bug描述写得好开发对你的观感也会好很多这对后续工作的推进帮助极大。3.3 性能测试相关理论加分项别丢笔试选择题和简答题里偶尔会穿插性能测试的内容比如QPS、TPS、响应时间、并发用户数、吞吐量这些概念。虽然占比不大但如果你完全不会就会很被动。我建议至少掌握这几个核心概念响应时间从发请求到收到响应的总耗时、吞吐量单位时间内系统处理的请求数、并发用户数同一时刻正在和系统交互的用户数、QPS每秒查询数、TPS每秒事务数。要能区分QPS和TPS的区别QPS偏查询TPS偏一个完整事务的处理。还有一个常考点是性能测试的流程需求分析、制定测试计划、脚本设计、执行测试、结果分析、调优建议。这个流程能背下来最好能结合自己的理解就更好了。比如结果分析时不能只看平均响应时间同时要看95%响应时间、错误率、资源使用率因为平均数容易被极端值带偏。对于校招来说性能测试一般不会考到特别深但如果你能在写测试用例时主动提到性能测试角度比如“在弱网环境下测试登录接口的响应时间”这个细节会让考官觉得你有性能意识属于加分项。4. 编程题实战模拟用一道题打通“测试开发思维”4.1 题目还原与读题分析我拿一道当时同类型的真题来模拟一下这类题目非常典型“给定一个字符串请实现一个方法将字符串中的每个单词反转但是单词之间的顺序保持不变。例如输入‘Hello World’返回‘olleH dlroW’。”这类题在LeetCode上叫“反转字符串中的单词III”难度属于简单。但笔试里考它目的不是考你会不会做而是看你的代码习惯和边界处理能力。读题时先抓几个关键信息每个单词反转、单词顺序不变、单词之间以空格分隔。然后要追问几个边界问题多个连续空格怎么办字符串为空怎么办字符串只有空格怎么办字符串开头结尾有空格怎么办这些边界问题能不能想到直接决定了你的代码是60分还是90分。笔试环境并不是每次都能跑代码验证所以你在纸上读题时就要养成“自己给自己出边界条件”的习惯。这个习惯很重要将来做测试开发你读需求文档时也是这样先看主流程再穷举异常场景。4.2 参考实现与逐行拆解这道题常见的解法是先按空格拆分、再逐单词反转、最后拼接。要注意的是Java里split函数的局限性如果直接用str.split( )多个连续空格会拆出空字符串可能影响结果。但既然题目没明确说明我们按常规英文单词和单空格场景处理同时主动去想边界。参考实现public String reverseWords(String s) { if (s null || s.length() 0) { return s; } String[] words s.split( ); StringBuilder result new StringBuilder(); for (int i 0; i words.length; i) { if (i 0) { result.append( ); } result.append(new StringBuilder(words[i]).reverse().toString()); } return result.toString(); }这段代码里我用StringBuilder来做拼接而不是直接用“”因为循环里频繁字符串拼接会产生大量中间对象虽然笔试数据量小无所谓但这个习惯要继续保持。如果你想让自己的答案更有展示度可以主动追问并处理空串场景。比如使用split( )对于多个连续空格会得到空字符串我们可以在拼接时跳过空串这样即使输入“Hello World”两个空格也能输出“olleH dlroW”。这个细节一旦你写出来说明你对输入条件的分析能力可能比你实现一个标准答案更让考官印象深刻。4.3 测试思维追加写完代码后你该检查什么代码写完了大多数人的习惯是直接交卷或者去跑下一题。但测试开发岗的笔试不一样你应该在代码后面追加一道“自查测试用例”的意识这才是跟普通开发的差别人间。即使题目没要求你心里也要过一遍这些用例输入“Hello World”预期“olleH dlroW”输入“Hello”预期“olleH”输入“”预期“”输入“I love coding”预期“I evol gnidoc”如果考虑多个空格输入“Hello World”两个空格你的代码输出是否符合预期输入“a”预期“a”这个动作本身就是测试用例设计的缩影跟你在真实工作中拿到一个函数后要做的第一件事完全一致先想怎么测再想怎么改。笔试中如果时间来得及还可以把测试用例以注释形式写在代码后面这个小举动极容易被阅卷人注意到属于很高的加分项。我还想提醒一点不要只盯着“正确解”写写完立刻复核一下自己的代码里有没有可能出现数组越界、空指针、边界循环错误。很多人LeetCode刷题时在IDE里能过但在纸笔环境下就容易翻车就是因为没有形成自查的习惯。这个习惯练好了笔试就稳了一半。5. 数据库与Linux容易被忽视的送分题5.1 SQL查询题这类题丢了分实在可惜数据库相关题目在笔试试卷里几乎必考但难度普遍不高基本上是课上教过的select、where、order by、group by、having、join这些内容。正因为不难反而容易被忽视等考完一对答案才后悔“这种题我本该拿满分的。”我遇到过的典型考法是给你两张表一张学生表学号、姓名、班级一张成绩表学号、课程、成绩然后让你写几个SQL查询。比如查询每门课程成绩最高的学生信息、统计每个班级的平均成绩并降序排列、查询所有课程成绩都大于80分的学生、查询哪些学生有挂科记录等。这里我特别想强调一个高频坑group by和having的组合使用。很多人记不清where和having的区别简单记法就是where是分组前过滤having是分组后过滤。比如“查询平均成绩大于80分的学生”这个条件必须先group by再having avg(score) 80而不能用where。另外一个容易出错的点是如果查询结果中既有聚合函数比如avg、max、count又有非聚合列那么非聚合列必须出现在group by中否则SQL执行会报错或逻辑不严谨。还有很多同学在IN子查询和JOIN之间犹豫不决其实两者某些场景可以互换但JOIN的性能通常更好笔试里面只要写出正确结果即可不用太纠结优化。SQL这种题没什么捷径就是考前把基本的增删改查写熟练把group by、having、join、子查询这几个重点练熟。只要练到位了这几十分几乎是白送的。5.2 Linux命令测试开发必备的底层技能Linux命令是测试开发笔试里的常客常考的题无非这么几类查看日志、查找文件、查看进程、查看端口、统计文本内容、修改权限。每类对应的几个典型命令一定要滚瓜烂熟。可能的方向查看日志文件最后100行tail -100 app.log实时查看日志tail -f app.log查找文件find /data -name *.log查看所有Java进程ps -ef | grep java查看某个端口占用情况netstat -anp | grep 8080或lsof -i:8080统计一个文件的行数wc -l app.log统计日志中某个关键字出现的次数grep -c ERROR app.log查看文件占用磁盘空间du -sh /data笔试里还有一个经典考法给你一个日志文件路径让你找出其中所有ERROR级别日志并统计每个小时出现的次数。这个组合题就涉及grep、awk、sort、uniq等命令的配合。虽然有点进阶但练一遍就会了属于性价比很高的投资。我的建议是不要光死记命令参数最好自己在环境里实际操作一遍。比如tail -f和tail -100的区别不实际看一遍你可能永远体会不深。Linux这套东西用了就记住了不用的话背再多也容易忘。5.3 日志分析实战从笔试到工作都适用的技能我见过不止一份小米这套题的考后回忆里提到日志分析相关的简答题这也是测试开发日常工作中每天都会碰到的事。所以我想多聊几句日志分析的真实操作逻辑。拿到一份日志第一步不是急着搜关键字而是先看日志体量。用wc -l看看文件多少行大致评估一下分析难度再head看一下日志格式规范不统一能不能直接grep。很多时间花在了“怎么找对格式”上面而不是“怎么找数据”。第二步是常用grep做粗筛把你要关注的关键词捞出来。比如线上反馈登录慢你先搜“Login”或“login timeout”定位到时间段看看响应时长分布。如果需要按时间维度聚合就要用awk把时间戳裁出来再sort和uniq去重统计。第三步才是定位细节找到具体的异常栈、错误码、超时时长等信息。这个过程非常依赖你的Linux功底。笔试里考察的Linux命令你以为是考察工具其实考察的是你将来能不能独立排查问题。所以把这个能力练好不只是考试有用更是职业生涯的基石。6. 备考路线与资源调整三轮复习法6.1 第一轮刷题打底重点吃透Java和数据结构如果你准备时间比较紧比如只有一个月我的建议是第一轮集中在Java基础和数据结构上这也是笔试里分数最集中、最有区分度的部分。Java基础方面把集合框架的源码过一遍重点看HashMap、ArrayList、LinkedList、HashSet、ConcurrentHashMap的实现原理多线程重点掌握synchronized、volatile、Lock、线程池、死锁这几个话题JVM重点了解内存模型、GC算法、类加载机制至少能说清楚堆和栈的区别、GC Roots是什么。数据结构方面不建议上LeetCode硬刷几百道题那样太耗费时间且效果不一定好。先把高频题型刷熟数组、字符串、链表、栈、队列、二叉树、二分查找、排序。每个类型刷10道左右经典题够应付大部分校招笔试了。时间安排上我建议每天留出固定两小时刷题用番茄钟法每40分钟休息5分钟保持专注度。刷题的时候不要只追求AC要习惯性地想时间复杂度和空间复杂度想边界条件想如果自己是测试会怎么设计用例。这套下来你的编码能力一定会有质的提升。6.2 第二轮系统补数据库、Linux和测试理论第二轮的着力点是计算机基础和测试理论。这一轮不需要太夸张的节奏每天一两小时即可主要是把知识框架搭起来。数据库把SQL标准语法过一遍重点练join、group by、having、子查询的常见组合再刷几套牛客网上的SQL题库基本就够了。Linux把高频命令整理成自己的笔记每类命令记几个典型案例动手在虚拟机上练一遍。测试理论方面把软件测试生命周期、测试用例设计方法等价类、边界值、因果图、判定表、缺陷管理流程、测试报告要点、各类测试类型的定义和应用场景都过一遍。不用背太深但要做到拿到一个题目就能把相关的知识点调动出来。第三轮再集中做模拟笔试。找一些往年的真题或者牛客网上的模拟试卷严格按照时间做一遍做完之后重点看错题把错题对应的知识漏洞补上。同时建议给自己建立一个“错题知识清单”不要记具体题目记背后的知识点。比如“HashMap扩容机制记混了”“group by和having顺序搞反了”考试前翻一遍这份清单比临时翻书效率高得多。6.3 给自己留一个真实的项目复盘很多同学的简历上写着“熟悉软件测试流程”但一问细节就说不出来这是校招面试里常见的尴尬。我建议在备考期间认真复盘自己曾经做过的任何一个项目哪怕是课程设计、毕业设计都行只要能讲清楚“我做了什么、数据怎么流转的、哪些环节可能出Bug、我如何验证它是正确的”就足够。测试开发的本质不是“会点工具”而是“具备工程化思维”。你不需要做过真正的自动化测试框架但你能不能用代码写一个小的工具函数能不能用数据库和Linux命令完成一次简单的数据统计能不能把一个功能拆成可验证的测试点——这些才是笔试题真正想看到的。我在实际工作中招过不少实习生最后能顺利转正的往往不是刷题量最大的那个而是读题最快、边界感最强、沟通最清楚的那个。而这三项能力笔试里就能看出来七八分。所以备考的时候你练的不仅是做题能力更是在训练自己未来的职业习惯。