diff --git a/scripts/.gitignore b/scripts/.gitignore new file mode 100644 index 00000000..6caf68af --- /dev/null +++ b/scripts/.gitignore @@ -0,0 +1 @@ +output \ No newline at end of file diff --git a/scripts/merge_into_book.py b/scripts/merge_into_book.py new file mode 100644 index 00000000..5a7e98ab --- /dev/null +++ b/scripts/merge_into_book.py @@ -0,0 +1,62 @@ +import os +import shutil +import re + +# Define a function named merge_markdown_files that takes a folder path and a file name as parameters and calls copy_img_folders and merge_markdown_content functions +def merge_markdown_files(folder_path, file_name,output_folder="output"): + current_root_dir = os.path.dirname(os.getcwd()) + # Use the os.walk() function to iterate over all subdirectories in the folder and store the result in a variable + walk_result = list(os.walk(folder_path)) + if os.path.exists(output_folder): + shutil.rmtree(output_folder) + # Loop through each tuple in the list + for dirpath, dirnames, filenames in walk_result: + # Loop through each directory name in the current subdirectory + for dir in dirnames: + # Check if the directory name is "img" + if dir == "img": + # Get the source path of the img folder by joining it with the directory path + src_path = os.path.join(dirpath, dir) + relative_path = os.path.relpath( os.path.abspath(dirpath),current_root_dir) + # print(f'relative_path {relative_path}') + # Get the destination path of the img folder by joining it with the file name and removing the extension + dst_path = os.path.join(output_folder,relative_path, dir) + # Copy the img folder to the destination path using shutil.copytree() + shutil.copytree(src_path, dst_path) + # Use the os.walk() function to iterate over all subdirectories in the folder and store the result in a variable + # Sort the list of tuples by the first element (the directory path) + walk_result.sort(key=lambda x: x[0]) + # Open a new markdown file in write mode using the with syntax + with open(os.path.join(output_folder, file_name), "w", encoding="utf-8") as output_file: + # Loop through each tuple in the sorted list + for dirpath, dirnames, filenames in walk_result: + # Sort the list of directory names in alphabetical order + dirnames.sort() + # Sort the list of file names in alphabetical order + filenames.sort() + has_section_name = False + # Loop through each file name in the current subdirectory + for file in filenames: + # Check if the file name ends with ".md" + if file.endswith(".md"): + if not has_section_name: + # Get the folder relative path by using the os.path.relpath() function + section_name = os.path.relpath(dirpath, folder_path) + # Write the section name as a header, followed by a newline character + output_file.write("# " + section_name.replace("\\","\n\n# ") + "\n\n") + has_section_name = True + # Open the markdown file in read mode using the with syntax + with open(os.path.join(dirpath, file), "r", encoding="utf-8") as file1: + # Read the content of the markdown file + content = file1.read() + # Write the file name as the title of the content, followed by a newline character + output_file.write("## " +file.replace(".md","") + "\n\n") + relative_path = os.path.relpath(os.path.abspath(dirpath),current_root_dir) + # print(f'relative_path {relative_path}') + # Replace any image path text in the content with the new location using re.sub() + content = re.sub(r"img\/(\w+\.(JPG|SVG|jpg|svg|png))", f"{repr(relative_path)[1:-1]}/img/\g<1>", content) + # Write the content to the new file + output_file.write(content+ "\n") + +# Call the function with the folder path and the file name as arguments +merge_markdown_files("../基础教程/A5-现代软件工程(更新中)", "现代软件工程.md") \ No newline at end of file diff --git a/基础教程/A5-现代软件工程(更新中)/第2步 - 个人与职业/第2章 - 专业能力/2.2 故事分析.md b/基础教程/A5-现代软件工程(更新中)/第2步 - 个人与职业/第2章 - 专业能力/2.2 故事分析.md index aecf6a50..f0a7ce48 100644 --- a/基础教程/A5-现代软件工程(更新中)/第2步 - 个人与职业/第2章 - 专业能力/2.2 故事分析.md +++ b/基础教程/A5-现代软件工程(更新中)/第2步 - 个人与职业/第2章 - 专业能力/2.2 故事分析.md @@ -24,7 +24,7 @@ - 开发语言掌握能力,比如 C++, Python, C#, Php, Java 等等。 - 设计能力和经验,比如大数据存储与处理经验、复杂系统搭建经验、大用户量的并发访问设计经验、训练神经网络模型的经验、手机应用开发的经验等等。 -- 一些著名的服务组件或框架的使用经验,比如 Web 服务器中的 Appache、消息队列中的 RabbitMQ、数据库 MySQL、分布式系统架构 Hadoop 等等。 +- 一些著名的服务组件或框架的使用经验,比如 Web 服务器中的 Apache、消息队列中的 RabbitMQ、数据库 MySQL、分布式系统架构 Hadoop 等等。 #### 2. 让技术面试官能看到项目经验 diff --git a/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/1. 测试 b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/1. 测试 deleted file mode 100644 index 9e739afe..00000000 --- a/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/1. 测试 +++ /dev/null @@ -1 +0,0 @@ -https://blog.csdn.net/super_vicky/article/details/99460617 diff --git a/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/16.0 软件测试.md b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/16.0 软件测试.md new file mode 100644 index 00000000..3b4fedc5 --- /dev/null +++ b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/16.0 软件测试.md @@ -0,0 +1,32 @@ + + + +上一部分我们综合探讨了软件开发设计和实现的原则和方法论,然而在软件产品最终交付给用户之前,软件的质量保障(QA,Quality Assurance)和测试(Testing)是不可或缺的环节。缺乏QA和测试的软件世界是灾难性的。1996年6月4日,阿丽亚娜5号运载火箭501在起飞的过程中由于SRI惯性参考系统出现软件故障,在发射不到一分钟内爆炸,“成就”了一场75亿美元的烟花秀;1998年4月20日,比尔盖茨在发布会现场演示Windows 98的即插即用功能时,连接扫描仪后系统崩溃,在无数现场媒体前“展示”了著名的Windows蓝屏。有效的质量保障技术虽然无法清除软件bug,但却可以帮助在更早的阶段发现软件缺陷,Fail fast,从而提升软件的可靠性、稳定性和可用性。 + +而软件测试是质量保障的核心手段。本章将聚焦于软件测试的应用实践、目标和基本概念,通过实际的工程问题帮助梳理软件测试的脉络,回答以下几个问题: +- 软件测试是什么? +- 测什么,谁来测,怎么测? +- 微软是如何做软件测试的? + + + + + +### 参考资料 + +- 《微软的软件测试之道》, Alan Page / Ken Johnston / Bj Rollison著,张奭 / 高博 / 欧琼 / 赵勇译,机械工业出版社 +- 《构建之法》,邹欣,人民邮电出版社 +- 《致命Bug:软件缺陷的灾难与启示》,金钟河/叶蕾蕾,人民邮电出版社 +- 《软件工程:实践者的研究方法》,Roger S.Pressman/Bruce R.Maxim著,郑人杰等译,机械工业出版社 +- 《软件测试之困:测试工程化实践之路》,肖利琼,人民邮电出版社 +- https://www.windowslatest.com/2018/04/25/its-been-20-years-since-windows-98-crashes-live-on-stage-with-bsod/ +- https://www.ibm.com/topics/software-testing +- https://en.wikipedia.org/wiki/Software_testing +- https://www.techtarget.com/whatis/definition/software-testing + + +### TODO list + +- 16.1 配图;项目背景:mobile edge testing? +- 本章面向对象:开发人员 or 面试测试人员? + diff --git a/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/16.1 木头与软件测试的故事.md b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/16.1 木头与软件测试的故事.md new file mode 100644 index 00000000..c17e2f23 --- /dev/null +++ b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/16.1 木头与软件测试的故事.md @@ -0,0 +1,78 @@ +## 木头与软件测试的故事 + +转眼之间,木头已来到自己职业生涯的第8个年头,本月初有一位新同事小陈入职,木头带领他一起完成了一次线上bug的排查。借由这次机会,小陈很快地熟悉了项目中的相关feature,定位到了代码中的问题,并在木头的帮助下得出了解决方案:需要改一行代码,然后加两行日志收集的代码方面进行修复情况跟进。 + +拿定主意,新人小陈熟练的打开IDE,写好并提交了代码,就找到木头,兴致勃勃地讲述了想法,打算一气呵成地完成代码签入、热修复(hotfix)、部署和发布,完成自己职业生涯的第一个“代码产品化”里程碑。木头见他热情可嘉,回想起了自己初入职场的青葱岁月,也没有直接泼冷水,打趣说道: + +“好啊,不过你这个里程碑肯定早晚会拿到,你先别急着合入代码修改,先针对这段改动丰富一下单元测试,然后最好自己也多测几轮,这样再上线,比较稳妥。这个feature虽然是新feature,不过生产环境目标用户数量也有好几万了。” + +“这...需要吗?一共就一行代码改动,加了个if判断,都是局部变量,不可能出问题啊。”小陈一脸狐疑的说道。他心想自己以往LeetCode战无不胜,写代码经常是一把过,这次就这么简单的改动的话,完全可以省去测试流程。 + +“哦,可是这里还加了日志输出,原来是没有这个调用的。”木头一边看着小陈的改动,一边说道。 + +```java + private void interceptRedirect(String redirectUrl){ + ... + traceLogger.infoWithArgs( + String.format("Redirect URL: %s", redirectUrl)); + ... + } +``` + +```java +// 以下是示例infoWithArgs的底层实现,并没有在本次修改中被小陈修改。 +public class TraceLogger { + ... + public void infoWithArgs(String message, Object... args){ + ... + info(String.format(message, args)); + ... + } + ... +} +``` + +“对对,不过这个能出什么问题吗,日志模块的接口到处都在调用,我这里就是把变量的值打印出来而已。而且这个方法貌似已经有一个单元测试在覆盖了,你看这里。” + +```java + public void testInterceptRedirect_NoException(String redirectUrl) { + ... + interceptor.interceptRedirect("https://www.bing.com/search?q=software+testing"); + ... + } +``` + +聊到此处,木头直觉事情没有那么简单,“你调用日志的时候,没有传入参数,却调用了infoWithArgs,嗯,这样会有问题吗?”。 + +“我从上面直接复制粘贴过来的,应该没问题吧?单元测试是通过的。” + +两人一起研究起了一下这段代码,并对现有的单元测试进行了扩展,提供了一些新的数据用例,实战了一下结对编程。没想到,两人很快发现在入参URL为某些特例(包含%a、%b或%c)的时候,字符串格式化语句会出现异常 `MissingFormatArgumentException` 报错,导致整个业务流中断。而这个所谓的特例,在这个业务场景中和代码逻辑中频次很高,可能会导致线上数千用户的体验中断。 + +```java + @Test + public void testInterceptRedirect_NoException(String redirectUrl) { + ... + interceptor.interceptRedirect("https://www.bing.com/search?q=software+testing"); + // 新增的用例会在原有代码上触发 `MissingFormatArgumentException` 异常 + interceptor.interceptRedirect("https://www.bing.com/search?q=%e5%be%ae%e8%bd%af%e4%b8%ad%e5%9b%bd"); + ... + } +``` + +小陈惊出一身冷汗,自己心心念念的职业里程碑,差点演变成大型翻车现场;本来是打算修复一个线上问题,没想到差点制造出新问题。这时的他再看木头,不由觉得木头周身有一圈佛光,是上天派来拯救他的。“看来一行代码改动也要仔细研究,而测试是很好的代码问题的检验手段,需要多下功夫研究研究。”小陈顿了顿,然后激动地说:“软件bug的代价太大,宁可错杀,不可放过。”小陈又燃了起来,不过这次却让木头很是欣慰,听的频频点头。 + +“哈哈,你讲的挺逗,确实如此,bug能咱们自己发现修掉,就不要让客户帮咱们体验。从某种程度上来说,编程是对逻辑复杂性的管理。咱们的项目代码行数是百万级别的,逻辑复杂,情境和用例非常多,每一处修改都有可能牵一发而动全身。全面的测试可以帮助我们在更早的阶段评估代码修改的影响。” + +木头接着说:“其实你不用后怕,咱们的代码合入之后,还会经过层层检测。代码合入主分支之后还会经过bvt测试、更全面的集成测试,热修复上线之前还会经过验收测试、回归测试以及压力测试,再部署到测试环境,进行内部的自测。之后都没问题,才可能发布到预生产环境、生产环境。所以你这个问题,大概率能够在上到预生产之前被拦截下来。我估计集成测试都过不了,哈哈。” + +小陈挠头附和打个哈哈,心想,这些你不早说,原来还有这么一大堆测试。 + +又聊了几句,两人看时间不早了,就由小陈着手把代码修复完整后提交了,等待其他同事帮忙评审,就先下班了。 + +“还有一条规则,周五下午坚决不发版。下周见!”木头大手一挥,消失在大楼转角。 + +今天发生的事情对小陈触动很大,回家后他依然在思考,为什么自己当时写代码时没有想到这个特例(corner case)?木头说的“全面的测试”,又如何理解其具体含义?一方面,他今天只接触了单元测试,而木头还提到了其他很多种类的测试。另一方面,测试团队似乎很重要,可以帮忙发现很多问题,而自己作为开发人员、代码修改的第一作者,和“全面的测试”之间的关系是什么?是否软件质量要依赖于测试团队的工作? + +最终,如果有了“全面的测试”,是不是软件质量就可以高枕无忧了? + +带着这样一个又一个问题,小陈查了查资料,看到一句“测试是为发现错误而执行程序的过程”,还没来得及梳理出脉络,就感觉困意袭来,于是洗漱睡觉,结束了充实的一天。 diff --git a/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/16.2 故事分析-软件测试的复杂性.md b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/16.2 故事分析-软件测试的复杂性.md new file mode 100644 index 00000000..d2f3d419 --- /dev/null +++ b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/16.2 故事分析-软件测试的复杂性.md @@ -0,0 +1,27 @@ +## 故事分析-软件测试的必要性和复杂性 + +软件测试的重要性是和软件所服务的用户数量正相关的:越是成熟的公司,越是大型的软件就越需要完善测试,层层把关。软件测试的复杂性会随着软件本身的复杂性的上升而上升。如果是简单明确的程序或者脚本,自测验证即可;而对于例如微软内部的Windows或者Office大型产品线,测试的计划需要在产品设计阶段就介入,在架构和组件层面要考虑软件的可测试性,确保Testable,并设计和逐步建立完善的、全方位的测试体系,来保障问题尽早被发现(Fail fast)。 + +对于微软这样用户规模很大(亿级别)的公司来讲,任何一次“小的”软件质量事故,哪怕是只有万分之一的概率出现,也可能会影响成千上万的用户,破坏体验、口碑,甚至演变成为公关事件,影响公司声誉,造成巨大的商业损失。 + +既然如此,什么能为软件产品的上线、版本更新带来信心呢?测试这一活动,通过衡量实际情况与预期之间差距,正是增加对软件质量信心的关键活动。团队在上线前,看到一份“测试通过”的测试报告,自然会更放心一点。 + + + +### 测试与质量保证 + +从刚刚木头和小陈的故事当中,我们也可以体会到这点:代码有单元测试覆盖,所以会小陈会觉得自己的修改有保障,获得了“迷之自信”;但实际情况是,代码依然存在严重问题。而小陈后来反思的时候,看到了书上的"测试是为发现错误而执行程序的过程",也得到了一些启发。这些共同说明: + +1. 开发人员的自测是有很大局限性的。 +2. 仅靠测试是无法保障产出高质量软件。 +3. 从心理学、活动意图角度上讲,测试不应该是为了增加信心的,不能让测试变成“自卖自夸”;而是应该以一种略带质疑的审视,假定软件有问题的前提下,努力的把问题找出来。这样的测试才可能会更有成效、更有意义。 + +故事中,小陈认为代码的修改量很小,并且是局部变量的改动,“问题不大”,忽视了所谓的“边界”情况。根据实践中的经验,软件开发中出现的问题往往不必和精巧的设计、核心的业务逻辑有必然联系,而更多出现在被疏忽的“边缘”环节上。而测试就是要发现软件错误和异常情况。 + +当今时代编程已经发生了更多的演化:我们有越来越多的类库、别人写好的方法可以调用,有越来越多的“轮子”、“巨人的肩膀”来加速功能实现。这就意味着,一行代码可能暗藏着很深的调用栈和很长的调用链条。木头作为资深的工程师,意识到即使是小的改动也可能引入问题,尤其是在复杂的软件系统、数据场景中。当软件足够复杂,“简单”的改动已经非常不可信,务必进行相应的测试,以避免潜在的问题。 + +木头作为经验丰富的同事,担任着指导和教育小陈的角色。他强调了测试的重要性,并解释了测试的流程和不同阶段的测试类型。在软件开发中,测试团队在保证软件质量方面的重要作用。然而质量并不是测试团队的“锅”,软件质量保障是整个团队的责任。 + +要做好测试,需要了解和运用一系列的测试知识和工具。木头也提到,不仅仅有单元测试,还有其他类型的测试,如集成测试、回归测试、压力测试等,并解释了这些测试环节在保证软件质量方面的作用:在不同层次和环境中验证软件的正确性和稳定性。 + +总的来说,软件测试发展至今,体系庞大、功能也很强大,但它不是万能的。它是确保软件质量的关键环节之一。开发人员应该积极参与测试,并与测试团队合作,打造体系,诚实勇敢地去发现问题、重视问题、面对问题、评估问题和最终解决问题,共同提高软件的质量和可靠性。 diff --git a/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/16.3 什么是软件测试.md b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/16.3 什么是软件测试.md new file mode 100644 index 00000000..2cc72c83 --- /dev/null +++ b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/16.3 什么是软件测试.md @@ -0,0 +1,101 @@ +## 什么是软件测试 + +软件测试似乎并没有所谓的“权威”的定义,说法众多,比较常见的说法是,软件测试是一种实际输出与预期输出之间的审核或者比较的过程。测试的意图是验证软件的行为,进而发现会导致系统失败的问题。结合前文,“测试是为发现错误而执行程序的过程”,提炼两个关于测试的重点: + +- 测试过程体现了实际输出与预期输出间的比较。 +- 要带着质疑的视角,提供客观、独立的结论,暴露软件实施的风险。 + +从时间要求上,测试这个过程可以很简短,也可以持续到所有利益相关者都满意为止。 + +### 以问题为导向 + +问题是测试的最重要的产出之一,谈及测试我们先全面的认识一下软件的“问题”。我们一般习惯称软件的问题为“Bug”,不同语境下也可以用为“Defect缺陷”、“Exception异常”、“Fault错误”和“Issue问题”等代指,他们分别强调了问题的不同方面或者不同部分。以下是一些由表及里的概念: + +| 概念 | 解读 | +| ------------------- | -------------------------------------------------- | +| Symptom 症状 | 问题的表征,如崩溃、严重的卡顿 | +| Issue 问题 | 一般是问题的表象的描述,代表了用户对这个问题的感知 | +| Defect 缺陷 | 可能指逻辑上的疏漏、不足之处和软件设计层面的问题 | +| Exception 异常 | 强调“和预期不符”,不一定是真的问题 | +| Fault/Error 错误 | 问题在程序层面的表现,如段错误 Segment Fault | +| Root Cause 根本原因 | 错误的根源,即导致代码错误的根本问题 | + +从问题表象到根本原因之间的距离可长可短,一个程序的崩溃、请求的失败,一般首先反映在用户体验上;开发团队可以将问题定位到一段出错的代码中;然而一段代码的错误或异常,可能是由其他代码导致的,比如Out of memory内存溢出(OOM)问题,往往报错的代码只是压倒骆驼的最后一根稻草,问题的根本原因可能隐藏在整体的软件内存管理、资源利用效率和方式上。再发散一点,一个软件问题的根本原因,可能和软件的工程流程、发布流程、团队管理甚至企业文化都有些许联系。 + +微软内部的产品组会在临近上线前组织“Bug-bash”(打虫子)大会,召集开发团队的所有人,产品、开发、测试,全都来对产品进行“Self-host”自用自测,发现问题就报告出来。这样做有很多好处,一方面,鼓励大家多多用自己开发的软件,增强主人翁精神;另一方面,团队发现问题和解决问题的人坐在一个屋子里、或者处在一个会议中,缩短问题解决的周期,效率很高。 + +一般用于描述一个问题的报告称为“Bug report”(缺陷报告)。它通常由以下几个主要部分组成,以帮助开发团队定位和修复问题: + +1. 标题: +Bug Report的标题应简明扼要地概括问题,使读者能够快速了解报告的主要内容。 + +2. 描述(Description): +描述部分详细说明了bug的情况,包括以下内容: + - 测试环境和准备工作:描述进行测试时所用的软件环境、硬件设备、配置等信息,以及为了测试而进行的准备工作。 + - 测试步骤:清晰列出每一步所执行的操作和动作,包括输入的数据、点击的按钮、导航的路径等。 + - 实际发生的结果:记录在执行测试步骤后实际观察到的结果,可能包括错误信息、异常行为、崩溃等现象。 + - 应该发生的结果:根据规范和用户的期望,描述在特定情况下应该发生的预期结果。 +3. 附加材料: +如果有必要,Bug Report可以附带其他补充材料,例如相关联的bug编号、输出文件、日志文件、调用堆栈的列表、截屏等。这些附件或链接有助于进一步的问题分析和复现。 +4. 其他字段: +在Bug Report中还可以包含其他字段,用于提供更多信息,如严重程度(Severity)、功能区域等。这些字段有助于对问题进行分类、评估和优先级排序。 + + + +Bug Report是一个重要的工具,它能够帮助测试团队和开发团队之间进行有效的沟通和合作,以及保障软件质量的提升。编写清晰、准确的Bug Report有助于减少问题的误解和漏洞,提高问题解决的效率和质量。 + +那么,测试是通过怎样的过程和方式把问题挖掘出来的呢? + +### 测试的分类:测什么和怎么测 + +软件测试的被测对象被称为Software Under Test(SUT)。然而,根据具体的测试目的和关注点的不同,测试可以分为如下几类: + +1. 功能验证 + + - **功能测试**(Function test):测试软件系统的设计功能是否符合规格要求。 + - **结构测试**(Structure test):白盒测试中对模块内部结构进行测试,验证代码的逻辑正确性和覆盖率。 + - **可用性测试**(Usability test):从使用的合理性和方便性等角度进行测试,发现人为因素或使用上的问题。 + - **配置测试**(Configuration test):测试软硬件系统平台对软件的支持和兼容性。 + +2. 性能验证 + + - **性能测试**(Performance test):验证系统是否满足规格中规定的性能要求,如响应时间、吞吐量、处理精度、缓冲区大小等。 + - **负载测试**(Load test):用满负荷长时间测试系统的稳定性(此时性能可以忽略)。 + - **压力测试**(Stress test):验证系统在超负荷和异常环境下的运行能力和稳定性(此时性能可以忽略)。 + - **可靠性测试**(Reliability test):评估系统的平均失效时间(MTBF)和故障停机时间(MTTR)。 + +3. 辅助测试 + + - **兼容性测试**(Compatibility test):测试不同版本间的兼容性,尤其关注文件存储/读取的兼容性,包括向下兼容和交叉兼容。 + - **安全测试**(Security test):验证系统的安全性,确保系统对于潜在攻击的防护措施有效。 + - **可访问性测试**(Accessibility test):验证系统对于聋哑人、盲人等特殊用户的易用性和无障碍访问性。 + - **本地化/国际化测试**(Localization test):主要验证软件在不同地区和语言环境下的本地化和国际化适配性,特别关注界面文字的正确性。 + + + +这些测试分类方式有助于测试团队根据不同的测试目标和需求,制定合适的测试策略和执行计划。此外,测试可以按照如下几个方面进行分类: + +#### 按照测试设计的方法分类 + +- **黑盒测试**:通过观察系统的输入和输出,以及对系统功能的期望行为进行测试,不需要了解系统内部的实现细节。黑盒测试在设计的过程中,把软件系统当作一个“黑箱”,无法了解或使用系统的内部结构及知识。也可以说是“Behavioral Test Design”,从软件的行为,而不是内部结构出发来设计测试。 +- **白盒测试**:基于对系统内部结构和代码的理解,设计测试用例来验证系统的逻辑正确性和代码覆盖率。在设计测试的过程中,设计者可以“看到”软件系统的内部结构。“白盒”并不是一个精确的说法,因为把盒子涂成白色,同样也看不见箱子里的东西。 +- **灰盒测试**:结合黑盒测试和白盒测试的特点,既关注功能验证,又考虑系统内部的结构和实现。 + +黑盒测试更接近用户视角,可以作为整体系统测试的一部分,验证系统在各种使用情况下的功能和行为。白盒测试对测试人员的要求更高,有时需要侵入系统、进行访问和修改,但更接近代码层面,可以发现潜在的逻辑错误、边界条件问题和代码覆盖不足的情况。“灰盒测试”还不是一个很流行的测试方法,处于“灰色地带”,好比无法窥见全貌却可以从某一个侧面或切面了解系统内部情况,同时观察外部行为,可能是一种先定条件下的测试(比如结合逆向工程的测试),对测试人员的综合能力要求更高。 + +#### 按照测试的实施方法分类 + +- **自动测试**:利用自动化工具和脚本执行测试,提高测试效率和一致性,适用于重复性较高的测试任务。 +- **手动测试**:通过人工操作和观察进行测试,适用于需要人的主观判断和复杂交互的测试场景。 + +测试并不一定要全部依赖于自动化测试,也不一定自动化越多越好;手动测试在某些情况下仍然具有必要性和重要性:例如探索性测试这种灵活性和创造性的测试方法在自动化测试中难以实现;手动测试能够模拟真实用户的操作和交互,更好地评估系统的用户体验;在某些情况下,系统的变动频繁或测试需求经常变化,手动测试具有更高的灵活性和适应性,能够快速调整测试策略和执行方式。 + +#### 按照测试的范围分类 + +- **单元测试**:对软件的最小单元(如函数、方法)进行测试,验证其独立性和功能正确性。 +- **集成测试**:测试不同模块之间的接口和交互,确保模块能够协同工作。 +- **系统测试**:以整个系统为被测对象进行测试,验证系统在各方面的功能和性能。 +- **验收测试**:由最终用户或客户进行的测试,以确认软件是否满足其需求和期望。 + +### 谁来测:测试人员的职业素养 + diff --git a/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/16.4 软件测试的设计方法.md b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/16.4 软件测试的设计方法.md new file mode 100644 index 00000000..e69de29b diff --git a/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/16.5 软件测试在微软.md b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/16.5 软件测试在微软.md new file mode 100644 index 00000000..e69de29b diff --git a/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/img/Slide1.SVG b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/img/Slide1.SVG new file mode 100644 index 00000000..cfee2397 --- /dev/null +++ b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/img/Slide1.SVG @@ -0,0 +1 @@ +SoftwareTesting软件测试Chapter-16第十六章 \ No newline at end of file diff --git a/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/img/Slide12.SVG b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/img/Slide12.SVG new file mode 100644 index 00000000..09d6f664 --- /dev/null +++ b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/img/Slide12.SVG @@ -0,0 +1 @@ +不同方面的测试种类功能验证Function testStructure testUsability testInstallationtest性能验证Performance testLoad testStress testReliability test辅助测试Compatibility testSecurity testAccessibility testLocal/Global-izationtest文档测试Spec reviewDesign reviewCode inspectionUser manualtest \ No newline at end of file diff --git a/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/img/Slide2.SVG b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/img/Slide2.SVG new file mode 100644 index 00000000..f2bb1ab0 --- /dev/null +++ b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/img/Slide2.SVG @@ -0,0 +1 @@ +阅读导图软件测试16.1木头与软件测试的故事16.2故事分析-软件测试的复杂性16.3什么是软件测试16.4软件测试领域知识16.5软件测试在微软 \ No newline at end of file diff --git a/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/img/Slide3.svg b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/img/Slide3.svg new file mode 100644 index 00000000..7dca9ad6 --- /dev/null +++ b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/img/Slide3.svg @@ -0,0 +1 @@ +质量保障vs.测试软件质量保障软件测试测试(Testing)提供一定的输入后,实际输出与预期输出间的比过程时机上与计划和设计一致实现后的输出动作和预期一致质量保障(QualityAssurance, QA)一切能够增加我们对产品质量信心的活动测试只是这类活动之一质量保障涉及到软件开发的全周 \ No newline at end of file diff --git a/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/img/Slide4.SVG b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/img/Slide4.SVG new file mode 100644 index 00000000..6db5846b --- /dev/null +++ b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第16章 软件测试/img/Slide4.SVG @@ -0,0 +1 @@ +全面的测试报告Agoodbug report标题例如:主页显示效果与设计不符传文件功能不能用描述环境复现步骤应该发生的结果实际发生的结果辅助信息关联的bug输出信息截屏严重程度SeverityLevel 1妨碍上线Level 2影响体验Level 3低感知度 \ No newline at end of file diff --git a/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第17章 测试工程化/17.0 从手动到自动.md b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第17章 测试工程化/17.0 从手动到自动.md new file mode 100644 index 00000000..e69de29b diff --git a/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/2.质量控制 b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第18章 质量保障/18.0 质量保障.md similarity index 58% rename from 基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/2.质量控制 rename to 基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第18章 质量保障/18.0 质量保障.md index 9a8e02cf..735202db 100644 --- a/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/2.质量控制 +++ b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第18章 质量保障/18.0 质量保障.md @@ -1,3 +1,10 @@ +$$ +软件 = 程序 + 软件工程 \tag{18.1} +$$ + +$$ +软件的质量 = 程序的质量 + 软件工程的质量 \tag{18.2} +$$ ### 运行期质量需求 @@ -18,3 +25,20 @@ - 可测试性(Testability):对软件测试以证明其满足需求规范的难易程度。 - 可维护性(Maintainability):当需要修改缺陷、增加功能、提高质量属性时,定位修改点并实施修改的难易程度; - 可移植性(Portability):将软件系统从一个运行环境转移到另一个不同的运行环境的难易程度。 + + +## 为什么软件质量保障重要 + +在微软,质量保障也被认为是Engineering Excellence, EE (可以翻译为卓越软件工程)的一部分。 + +客户对产品的评定是信任的指标,必须赢得并持续保持。微软云质量工程是一项全公司努力,旨在确保微软云成为全球最可靠的分布式云。 + +卓越是一种通过训练和习惯获得的艺术。 + +我们之所以行为正确,不是因为我们有美德或卓越,而是因为我们行为正确,因此才有了美德或卓越。 + +我们反复做的事情塑造了我们,因此卓越不是一种行为,而是一种习惯。——亚里士多德 + +质量和卓越一样,不是你可以简单发货和勾选清单的东西。它需要在开发和服务生命周期中进行持续的、习惯性的投入。一个人、一个团队不能单独对质量结果负责。我们所有人都要对质量结果负责。 + +为了赢得客户的信任,我们必须在整个开发和服务生命周期中专注于客户。这始于任何代码编写之前,理解和衡量客户的目标,并将它们用于设计、实施、改进和运营我们的服务。 \ No newline at end of file diff --git a/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第18章 质量保障/风险管理.md b/基础教程/A5-现代软件工程(更新中)/第7步 - 测试与质量/第18章 质量保障/风险管理.md new file mode 100644 index 00000000..e69de29b