测试游戏开发(译文)
By robot-v1.0
本文链接 https://www.kyfws.com/games/testing-for-game-development-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 55 分钟阅读 - 27059 个词 阅读量 0测试游戏开发(译文)
原文地址:https://www.codeproject.com/Articles/1114542/Testing-for-Game-Development
原文作者:Ashley Davis
译文由本站 robot-v1.0 翻译
前言
Covers theory, principles and practical techniques to help your testing efforts.
涵盖理论,原理和实用技术,以帮助您进行测试. 首次发表于(First published at) 可能出错的地方(What Could Possibly Go Wrong) .(.) 最重要的测试规则就是做到这一点.(The single most important rule of testing is to do it.) 克尼根`派克1999(Kerningham Pike 1999) 你会编程游戏吗?是?然后,本文适合您.使用哪种语言,引擎,API或平台都没有关系.无论您制作了多少游戏或计划制作多少游戏,甚至游戏的大小都没有关系.本文仍然适合您.因为无论您创建哪种游戏,都需要进行测试.如果您不亲自尝试,就永远不会交出自己制作的东西,对吧?(Do you program games? Yes? Then this article is for you. It doesn’t matter what language, engine, API or platform you use. It doesn’t matter how many games you’ve made or plan on making or even the size of your games. This article is still for you. Because no matter what game you create, it will require testing. You would never hand over something you’ve made without giving it a go yourself, would you?) 将代码打包在一起并放在那里(Slapping code together and putting it out there) 牛仔风格(cowboy style) 并非最佳做法.我们称之为更改代码和追踪错误的循环(isn’t exactly best practice. We call the cycle of changing code and chasing bugs)**虫子(bug) hack鼠(whack-a-mole) **.这种浪费的过程导致程序员压力的滑坡和决策能力越来越差.(. This wasteful process leads to a slippery slope of programmer stress and increasingly poor decision making.) 您需要知道您刚刚编写的代码可能会工作,甚至无法提交到(You need to know that the code you just wrote is likely to work before even committing to) 版本控制(version control) .不仅如此,您还需要知道自己不只是(. More than that you need to know that you didn’t just) 打破别的东西(break something else) 您已经测试过的.(that you had already tested.) 在本文中,我们涵盖:(In this article we cover:)
-
我们的测试理念.(Our philosophy of testing.)
- 通过测试指导开发,而不是通过测试跟随开发的更常见方法.(Guiding development through testing, instead of the more common approach of having testing follow development.)
- 了解为什么测试驱动的开发很重要.(Understanding why test driven development is important.)
-
流程,技术和测试技术.(Process, techniques and technologies for testing.)
-
简要介绍Unity引擎中的测试,因为我们在Real Serious Games中使用了它.(A brief look at testing in the Unity engine, since we use it at Real Serious Games.) 本文主要面向程序员,尽管其他学科也可以从中受益.我们的目标是尽可能扩大范围,此处的知识借鉴了游戏行业的多年经验(以及相关的痛苦).我们相信,任何水平的开发人员都会有收获.(This article is intended mostly for programmers, although the other disciplines can benefit as well. We aim to be as broad as possible and the knowledge here draws on many years of experience (and associated pain) in the games industry. We believe there will be something to take away for any level of developer.) 质量检查注意事项(A note to QA) 本文较少涉及(This article is less about)**质量保证(quality assurance)**以及有关将测试作为开发过程中不可或缺的一部分的更多信息.我们在这里所说的话并没有减少对一个好的QA部门的需求.我们认为,优秀的质量检查部门应紧密合作,并与开发团队紧密集成,并积极参与产品的开发.(and more about testing as an integrated part of the development process. Nothing we say here diminishes the need for a good QA department. We believe that a good QA department should work closely and be tightly integrated with the development team and actively involved in building the product.)
内容(Contents)
目录(Table of Contents)**产生于(generated with) DocToc(DocToc) **
- 结果(Outcomes)
- 经过良好测试的软件的属性(The attributes of well tested software)
- 哲学(Philosophy)
- 自动化(Automation)
- 处理(Process)
- 测试类型(Types of Testing)
- 自动化测试的类型(Types of automated testing)
- 技巧(Techniques)
- 技术(Technology)
- 统一(Unity)
- 结论(Conclusion)
- 关于作者(About the Authors)
- 关于审稿人(About the Reviewers)
结果(Outcomes)
测试能给您带来什么?这个问题似乎并不难回答.(What does testing give you? This question doesn’t seem that difficult to answer.)测试可以验证您的软件是否正常,对吗?(Testing verifies that your software works, right?) 是.但是我们可以做得比这更深入,而且可以更加具体.测试会验证您的软件是否按预期工作.更重要的是,它可以验证您的软件不会产生意想不到的后果(例如,格式化硬盘,除非它当然是格式化程序!).(Yes. But we can go deeper than that and we can be more specific. Testing verifies that your software works as intended. More importantly it verifies that your software doesn’t exhibit unintended consequences (for example formatting your hard drive, unless of course it is a format program!).) 这是我们的主要原因(That’s the main reason we)**做(do)**测试,但是还有许多其他后果,这些副作用可以改善我们的流程,改善我们的产品并帮助我们保持理智.让我们看看其中的一些.(testing, however there are many other consequential side effects that improve our process, improve our product and help keep us sane. Let’s look at some of these.) 测试可以帮助我们了解我们的软件(Testing helps us understand how our software)实际有效(actually works).不可低估.您是否回到了3个月前编写的代码?您还了解它是如何工作的吗?添加一个开发人员团队,沟通问题,复杂的需求,不断变化的范围和不断发展的设计. 3个月后,您仍然了解它的工作原理吗?大型复杂软件展览(. This can’t be understated. Have you ever returned to code you wrote 3 months ago? Do you still understand how it works? Add a team of developers, communication issues, complex requirements, changing scope and evolving design. 3 months later, do you still understand how it works? Large and complex software exhibits) 紧急行为(emergent behavior) 而且从来没有像我们希望的那样可预测.对于游戏尤其如此.(and is never as predictable as we would like it to be. This is especially true for games.) 结合复杂的游戏逻辑和不可预测的玩家行为,您是否确信自己的游戏将在每种情况下都做出优雅的反应?测试会产生对产品的知识和理解.这减少了不确定性,从而降低了产品风险.我们不仅在谈论游戏会附带隐藏问题的风险,尽管这肯定是我们已经看到的问题,甚至影响到最大的AA游戏.我们也正在谈论建立(With the combination of complex game logic and unpredictable player behaviour, are you confident your game will react gracefully in every situation? Testing generates knowledge and understanding of the product. This decreases uncertainty which in-turn reduces product risk. We are not just talking about the risk that the game will ship with hidden issues, although that’s certainly a problem that we have seen affect even the largest of the triple A games. We are also talking about the risk of building the)错误的事情(wrong thing),这个问题在软件开发中非常普遍.当然这可能更难(, a problem that is so prevalent in software development. Of course this can be harder to)**固定(pin-down)**在游戏开发中,但是只有通过玩和测试游戏,您才能更好地了解产品的含义以及产品的发展方向.(in game development, but only by playing and testing your game will you develop a better understanding of what the product is and where it should be heading.) 测试在很大程度上可以自动化.这需要大量的时间和精力,并且永远无法完全取代手动测试的需求,但是它可以消除大部分(Testing to a large extent can be automated. This requires considerable time and effort and can never fully replace the need for manual testing, however it can remove the bulk of)重复测试(repetitive testing).无可否认,很难实现自动化测试.但是,当您这样做时,它将变成使您的项目保持在一起的脚手架,并且可以在不断变化和持续发展的情况下向前移动并保持稳定的轨道.如果没有自动化测试,则要使软件随着时间的推移保持工作非常困难-尤其是当它被许多手触摸并快速进步时.(. There is no denying that it can be difficult to achieve automated testing. But when you do, it becomes the scaffolding that keeps your project together and the rails on which it can move forward and remain stable in the face of repeated changes and ongoing evolution. Without automated testing, it is much more difficult to keep software working over time - especially when it is being touched by many hands and rapidly progressed.) 测试可以改善计划和设计.为(Testing can improve planning and design. Any effort made to)**认为(think)**在进行编码之前,极大地提高了第一次正确设置(或至少更接近商标)的几率.制定测试计划有助于您了解前进的方向.这可以帮助您抛弃繁琐的工作,这些工作很耗时,但最终并没有为产品增加价值.及早消除不必要的范围是最有效的方法之一(before coding vastly improves the odds of getting it right the first time (or at least much closer to the mark). Having a test plan helps you understand where you are heading. This helps you jettison the busy work, those tasks that take time but ultimately don’t add value to the product. Culling unnecessary scope early and quickly is one of the most effective)**生产力提高(productivity enhancements)**你(们)能做到.因为您将其深思熟虑并将其作为测试计划进行明确表述,所以拥有一个明确定义的概念有助于巩固和完善您的愿景.这种前瞻性的想法可以帮助您发现愿景中的缺陷,也可以帮助您拒绝那些您认为行不通的想法.在可能的情况下,您应该尽早拒绝坏主意,然后再为他们流血.(you can make. Having a well defined concept, because you thought it through and articulated it as a test plan helps solidify and refine your vision. This forethought can help you identify flaws in the vision and can help you reject ideas that you decide aren’t going to work. Where possible you should reject bad ideas at an early stage before you have shed blood for them.)
经过良好测试的软件的属性(The attributes of well tested software)
在开始测试的哲学和技术之前,我们应该首先查看经过良好测试的软件的所需属性.正是出于满足这些属性的需要,我们才开始测试之旅.(Before we get into the philosophy and techniques of testing, we should first look at the desired attributes of well tested software. It is from the need to meet these attributes that we start our testing journey.) 完整性(Completeness) 代码是否完成了它打算做的所有事情?(Does the code do everything it is meant to do?) 正确性(Correctness) 代码可以正常工作吗?(Does the code work without error?) 性能和资源使用(Performance and Resource Usage) 代码是否具有可接受的性能和资源使用率?(Does the code have acceptable performance and resource usage?) 可靠性/稳定性(Reliability/Stability) 代码是否可靠运行?代码是否可以优雅地处理意外事件和错误数据?(Does the code work reliably? Does the code handle unexpected events and bad data gracefully?) 娱乐(仅用于游戏的奖励质量)(Fun (bonus quality just for Games)) 它能做到所有这些,并且游戏仍然很有趣吗?(Does it do all that and is the game still fun?) 现在有很多问题需要解决,但我们的目标并不是全面得分.许多软件开发都与完成工作所需的权衡,判断调用和平衡行为有关,在许多情况下,足够接近就必须足以胜任.(Now that’s a lot of boxes to tick, however we aren’t aiming at a perfect score across the board. So much of software development is about the trade-offs, judgement calls and balancing acts required to finish the job and in many cases near enough has to be good enough to get over the line.) 作为游戏开发者,这是我们常关注的最后一个属性.虽然我们将在此处讨论的大多数技术都无法用于测试(As game developers it is the last attribute that is so often front and center in our minds. While most of the techniques we’ll discuss here are useless for testing the)**好玩的品质(fun quality)**您的游戏(将其交到玩家手中永远是您的最佳选择),我们可以保证不满足任何其他这些素质(of your game (putting it in players hands is always your best option for that), we can guarantee that not meeting any of these other qualities)**将(will)**对游戏产生不利影响,因为根据定义,由于错误或性能不佳而导致您无法玩的游戏(have a detrimental effect on the fun, because a game that you can’t play due to bugs or poor performance is by definition)不好玩(not fun).(.)
哲学(Philosophy)
通过测试指导开发过程(aka(Guiding the development process by testing (aka) **测试驱动开发(test driven development)**要么(or)TDD(TDD) )是我们理念的重要组成部分,但我们不仅在谈论单元测试.在编码之前进行的任何思考,计划或参与测试活动的努力都将对开发产生积极影响,我们认为这是测试驱动开发的一种形式,尽管它可能更接近于其他开发人员通常认为的开发形式.() is a major part of our philosophy but we aren’t just talking about unit tests. Any effort made to think about, plan or engage in test activities before coding will have a positive impact on development and we consider that to be a form of test driven development, although it might be closer to what other developers normally consider to be)** 行为驱动的发展(behaviour driven development) **.(*.*) 您第一次接触TDD可能是在撰写本文时(*Your first exposure to TDD will likely have been when writing*) 单元测试(unit-tests) 在里面(*in the*)** 首先测试(test first) **方式.我们从TDD和单元测试开始,尽管我们已经意识到TDD也可以在没有单元测试和任何形式的测试的情况下应用.(*manner. We started with TDD and unit-testing although we have since realised that TDD can also be applied without unit-tests and without any kind of*) 自动化(automation) (尽管自动化测试非常有益,通常是TDD的最终目标).(*(although automated testing is extremely beneficial and usually the end goal of TDD).*) 我们的目标是(*We aim to be*)**注重结果(*outcome orientated*)**.结果如何?我们的目标是什么?我们如何衡量我们的成功?结果是否提供了超过其开发成本的价值?这些是您应该回答的问题.当您了解项目时,很可能会随着时间的流逝而得出答案.测试驱动的开发需要了解您的方向并关注结果.在开始之前,您必须了解自己的方向并且能够计划.如果您不知道,那就花点时间,尝试一下原型来测试您的想法,然后回到测试驱动的过程.(*. What is the outcome? What are we aiming at? How do we measure our success? Does the outcome provide value that outweighs the cost of its development? These are questions you should answer. You will most likely develop the answers over time as you come to understand your project. Test driven development requires an understanding of your direction and a focus on the outcome. You must know your direction and be able to plan before you start. If you don’t know this, then take some time out, hack together a prototype to test your ideas, then come back to the test driven process.*) 我们的目标是(*We aim to have a*)**质量观念(*quality mindset*)**.这意味着我们的目标是获得高质量的结果.我们如何定义质量?在这里无法解决,这意味着针对不同项目,不同情况下不同人群的不同事情.但是,我们确实提倡(*. This means we are aiming at a high quality outcome. How do we define quality? That can’t be addressed here, it means different things to different people in different situations for different projects. We do however promote a*)**缺陷第一(*defect first*)**开发过程.也就是说,我们希望在可能的情况下在添加功能之前先修复错误.我们攻击(*development process. That is to say that we prefer, where possible, to fix bugs before adding features. We attack*)** [https://zh.wikipedia.org/wiki/技术债务(*https://en.wikipedia.org/wiki/Technical_debt*)](https://www.codeproject.com(<a class=) )">技术债务(*)">technical debt*)**在项目的整个生命周期内保持稳定.越来越多的缺陷等同于项目的越来越多的风险(*head on to maintain stability over the life of the project. Mounting defects equates to mounting risk that a project*)**不会准时发货(*won’t ship on time*)**.最大限度地减少缺陷和技术债务有助于我们保持快速的变更步伐和较低的实验成本.测试有助于建立以质量为中心的思维定势并推广高质量的产品.这也许是显而易见的,但是必须说,构建旨在按预期工作且几乎没有意外问题的高质量产品是测试的目标.(*. Minimizing defects and technical debt helps us maintain a rapid pace of change and a low cost for experimentation. Testing helps build a quality-focused mindset and promotes a high-quality product. This might be stating the obvious, but it has to be said that building a high quality product that works as intended, with minimal unanticipated issues is the goal of testing.*) 我们的理念意味着我们试图预先定义我们的方向和成果.当然,我们不一定总是做到正确,但是至少我们总是知道自己在哪里(*Our philosophy means that we attempt to define our direction and outcomes up front. Of course we don’t always get that right, but at least we always know where we are*)**应该去(*supposed to be heading*)**.我们必须保持警惕,并不断监测前进的方向.我们必须准备改变路线,以保持竞争力并能够打造出最好的游戏.有时候,我们必须退后一步,根据需要进行重新评估和重新计划.(*. We must be vigilant and constantly monitor our heading. We must be ready to change course to remain competitive and be able to build the best game possible. There are times when we must take a step back, re-evaluate and replan as necessary.*) 那么测试驱动的开发如何帮助我们实现目标(*So how does test driven development help us achieve our*)**经过良好测试的软件的属性(*attributes of well tested software*)**?通过我们的理念和过程,我们可以…(*? Through our philosophy and process we can…*) 定义可接受(*Define acceptable*) 每个属性的可接受质量水平是多少?这取决于目标硬件,受众和游戏类型.测试驱动的开发迫使您提前计划.毕竟,您必须知道要测试什么.(*What is the acceptable level of quality for each of the attributes? That depends on the target hardware, audience and game genre. Test driven development forces you to plan ahead. You have to know what to test after all.*) 确定何时我们无法接受(*Identify when we aren’t meeting acceptable*) 每次添加或修改功能时,您都可以通过查看测试结果来了解其影响.当出现问题时,我们会记录添加的内容及其对游戏的影响.(*Every time a feature is added or modified, you’ll know the impact of it by looking at the output of testing. When something goes wrong we have a record of what was added and how it impacted the game.*) 估计计划外范围变更的影响(*Estimate impact of unplanned scope changes*) 您正在开会,有人想出新主意.所有的头都转向你,一个声音响了.(*You’re in the middle of a meeting and someone comes up with a new idea. All heads turn to you and a voice rings out.*)**我们可以做到吗?(*Can we do it?*)**幸运的是,您掌握了最近的指标,并且可以提供经过适当教育的猜测作为回应.(*Luckily, you have your recent metrics in hand and you can provide a reasonably educated guess in response.*) 我们最重要的两个原则是(*Two of our most important principles are*)**保持工作(*keep it working*)**和(*and*)**测试不是一个阶段(*testing is not a phase*)**.对自己重复这些.将它们放在显示器旁边的墙上.如果试图以您满意的节奏或别人要求的节奏推进项目,则您无法遵守这两个原则,则意味着您失去了对流程的控制.您将失去保持快速步伐的能力,估计任务的能力将会减弱.(*. Repeat these to yourself. Put them on the wall next to your monitor. If, in the attempt to move the project forward, perhaps at a pace you’re happy with or perhaps at a pace that someone else is demanding, you cannot keep to these two mantras, it means you’re losing control of your process. You’ll lose the ability to keep a rapid pace and your ability to estimate tasks will be diminished.*) 最终,有关测试驱动开发的主要内容是编码之前的计划是(*Ultimately the main takeaway about test driven development is that planning before coding is*)**总是(*always*)**一个好主意.(*a good idea.*)
自动化(Automation)
自动化在游戏开发中非常有用.这将花费很长时间,而且容易出错,并且容易出错,并使它们快速,可重复,可靠,并且有可能释放您的时间来处理真正重要的事情.这些额外的时间可以帮助您专注于制作更好的游戏.(Automation is so useful in game development. It will take long, drawn out and error prone processes and make them fast, repeatable, reliable and has the potential to free up your time for the things that really matter. This extra time can help you concentrate on making a better game.) 然而,建筑物自动化是昂贵且费时的.从长远来看,它是物有所值的,但您必须确保它不会从最初真正制作游戏中分心.毕竟,您必须完成该游戏以确保您确实可以长期生存.(Building automation, however, is expensive and time consuming. In the long term it pays for itself, but you have to make sure it doesn’t distract too much from actually making your game in the first place. After all you must finish that game to ensure that you do actually survive for the long term.) 您将需要权衡在自动化上投入多少时间.好处很明显,但是成本可能很高.自动化成本应在项目生命周期内摊销.以带时间限制的增量来发展您的自动化系统,这将防止您在系统上花费太多时间.随着时间的流逝,您将构建出可以用于下一个项目以及随后的项目的技术和工具工具箱.如我们所说,这是一项长期投资.随着时间的流逝,自动化需要更少的工作,并且当您的项目通过自动化测试框架保持正常运行时,收益最终将大大超过成本.有人提交更改会破坏您的构建或现有功能时,将向您发送通知.这样的系统使管理起来更加容易(You will need to make the trade-off as to how much time to invest in automation. The benefits are clear, but the cost can be high. The cost of automation should be amortized over the lifetime of your project. Evolve your automation system in time-boxed increments, that will prevent you spending too much time on it. Over time you will build out your toolbox of techniques and tools that can be carried over to the next project and the one after that. Like we said, it’s a longer term investment. Over time automation requires less work and the benefits will eventually massively outweigh the costs when your projects are kept on the rails by your automated testing framework. The moment someone commits a change that breaks your build or existing functionality, you will be sent a notification. A system like this makes it much easier to manage)技术债务(technical debt).(.) 你是如何开始的?从自动化构建过程开始,并创建一个(How do you get started? Start with automating your build process and creating a)**持续集成(continuous integration)**系统(稍后会详细介绍).也许然后将您执行3次或更多次的其他任务自动化.不必太担心它的工作原理^只需确保每个任务(system (more on that later). Maybe then automate other tasks that you do 3 or more times. Don’t worry too much about how this works… just make sure that each task is)**价值(worth)**自动化,并且80%或更多的工作负载是自动化的.这样可以节省您很多时间.请记住,自动化可能会很昂贵,自动化某些东西所花费的时间应该远远超过手动完成该任务的成本,如果不这样做,那么就不值得进行自动化.(automating and that 80% or more of the workload is automated. That’s going to save you so much time. Remember that automation can be expensive, the time it takes to automate something should vastly outweigh the cost of doing that task manually, if it doesn’t, then it’s just not worth automating.) 建立编写自动化测试的基础.(Build up to writing automated tests.)**单元测试(Unit tests)**需要大量的技能,工作和照顾,并且对代码的设计有很大的影响(很好的影响,但是花费时间才能正确).考虑为最重要,最困难或最麻烦的代码保存单元测试.(take a lot of skill, work and care and have a large impact on the design of the code (a good impact, but time consuming to get right). Consider saving unit tests for your most important, difficult or troublesome code.)**整合测试(Integration tests)**实施起来更容易,而且可以带来更多收益.集成测试对代码设计的影响也较小,这使为现有代码构建集成测试更加容易.(are easier to implement and they give more bang for buck. Integration tests also have less impact on the design of the code, this makes it easier to build integration tests for existing code.)**烟雾测试(Smoke tests)**在最终版本上运行,并且到目前为止最简单,因此值得从它们开始.有关这些类型的测试的更多信息,请参见下文.(are run against the final build and are the easiest by far so it’s worth starting with them. More on these types of testing below.)
处理(Process)
当我们开发软件时,我们在一个过程中工作.如果您不熟悉开发,那么您可能仍在创建过程.如果您已经进行了一段时间,则可能仍在创建过程.我们之所以这样说,是因为软件开发过程是一个不断发展的系统.必须进行更改以适应公司,团队和项目不断变化的需求.始终在寻找改进的过程,包括删除其中的一部分,因为它们不再带来价值.(When we develop software we work within a process. If you are new to development then you are probably still creating your process. If you have been doing this for some time you may still be creating your process. We say this because the software development process is an ever evolving system. It must change to fit the changing needs of the company, the team and the project. Always be on the lookout for improvements to the process, including dropping parts of it because they no longer deliver value.) 测试必须符合我们的开发流程.不应将其视为一个单独的阶段,也不应视为其他部门的责任.测试是开发的内在部分,与开发有着千丝万缕的联系.请记住(Testing must fit within our development process. It should not be considered a separate phase or the responsibility of a different department. Testing is an intrinsic part of development and inextricably linked to it. Remember that)**测试不是一个阶段(testing is not a phase)**它与开发过程紧密相关.测试在开发之前,之中和之后进行.整个过程应该是迭代的,(and it is tightly bound to the development process. Testing happens before, during and after development. The whole process should be iterative and) 敏捷(agile) 来自先前迭代的反馈会影响当前迭代,依此类推.(with feedback from the previous iteration influencing the current iteration and so forth.) 测试驱动开发的一般过程是(The general process of test driven development is to)设定期望,编写代码并添加产品功能,然后验证代码和功能是否符合最初设定的期望(set expectations, write code and add product features, then verify that the code and features meet the expectations that were originally set).使用单元测试进行TDD时(. When doing TDD with unit tests the)**设定期望(set expectations)**部分涉及写作(part involves writing)**实际(actual)码.当然,TDD的替代方法是传统的开发方法:(code. The alternative to TDD of course is the traditional development method:)编写产品代码,手动测试其功能,然后重复(write product code, manually test that it works, repeat).(.) TDD的关键是在编码之前了解您的结果并设定期望.如果您正在编写自动化测试,那么您的期望将以代码表达.如果您不这样做,则无论出于何种原因,请用英语写下您的期望:通常称为(The key to TDD is understanding your outcomes and setting expectations before coding. If you are writing automated tests then your expectations will be expressed in code. If you aren’t doing this, for whatever reason, write your expectations down in English: this is commonly called a) 测试计划(test plan) .无论您编写自动化测试还是只是在纸上写下您的期望都没那么重要,关键在于您了解要达到的目标,并且有一个计划可以进行验证.(. Whether you write automated tests or just write down your expectations on paper is less important, the point is that you understand what you are trying to achieve and you have a plan to verify against at) 代码完成(code complete) **.或者将TDD与单元测试和自动化相结合,意味着您可以在将来继续自动运行我们的测试,从而确保您的代码永远不会(. Or course TDD combined with unit tests and automation means that you can continue to run our tests automatically into the future, thus ensuring that your code is never)**偶然(accidentally)**如果没有自动化,这种情况似乎经常发生,并且随着更多开发人员加入团队,情况变得更糟,尤其是对于那些为了满足产品不断变化的需求而迅速发展的代码而言.(broken, something that seems to happen quite frequently without automation and gets worse as more developers are added to the team and especially so for code that is rapidly evolving to meet the changing needs of the product.) 在我们看单个流程之前(Before we look at the flow of a single) 迭代(iteration) ,警告:不同的公司和团队有不同的需求,因此不要害怕改变,改变它并使它为您服务.当您需要开拓自己的道路时,不要害怕扔掉现有的系统.充分利用现有资源,构建适合自己需求的流程.(, a caveat: Different companies and teams have different needs, so don’t be afraid to take this, change it and make it work for you. Don’t be afraid to throw out existing systems when you need to forge your own path. Take the best of what’s out there and build your own process, perfectly suited to your own needs.) 在阅读本文时,请不要假设我们的意思是迭代将完全隔离(While you are reading through this please don’t assume that we mean that an iteration will be a perfectly segregated) 瀑布(waterfall) .软件开发是一个混乱而混乱的业务,很少是如此简单,但是我们确实需要展示测试如何适应流程,因此让我们来看看.(. Software development is a chaotic and messy business and it is rarely this simple, but we do need to show how testing fits the process so let’s see how.) 话虽如此,典型的开发迭代可以分为以下步骤:(With that said, a typical iteration of development could be broken down into the following steps:) 1.原型(1. Prototype) 可选的.如果您已经知道自己做的很好,可以开始计划,那么这是不必要的.要弄清楚您要去的地方,您应该制作原型.这里的关键是(Optional. This is unnecessary if you already know what you are doing well enough to start planning. To figure out where you are heading you should prototype. The key here is)最小的努力(minimal effort).知道您需要回答的重要问题是什么.原型仅足以回答这些问题.刻意快速地工作,偷工减料,不用担心测试.确保工作是(. Know what the important questions you need answered are. Prototype only enough to answer those questions. Purposefully work quickly, cut corners and don’t worry about testing. Make sure the work is) 有时间限制的(time-boxed) .不要擦拭工作.抛光的原型(. Do not polish the work. Prototypes that are polished and)**差不多(pretty much)**做这项工作往往最终进入生产.有时这可以解决问题,而其他时候原型的伪劣做工会在项目结束前多次叮咬您.(do the job often end up going into production. Sometimes this works out ok, other times the shoddy workmanship of the prototype will bite you many times before the end of the project.) 2.产品规划设计(2. Product planning and design) 计划产品的下一个增量.就像(Plan the next increment of your product. This is like)**冲刺计划(sprint planning)**如果你在做(if you are doing) Scrum(Scrum) .专注于结果.您的主要目标是什么?您要交付什么?它带来什么价值?它为什么如此重要?(. Focus on the results. What is your major goal? What are you going to deliver? What value does it bring? Why is it important?) 代码设计也可以是其中的一部分,但是在这里不要过多地关注它.我们通过开发来促进设计,也就是说,技术计划和代码设计(例如测试)应在编码之前直接进行.我们认为这些活动是开发过程中不可或缺的一部分.(Code design can be part of this as well, but don’t focus too much on it here. We promote design through development, that is to say that technical planning and code design, like testing, should be done directly before coding. We feel that these activities are an intrinsic and ongoing part of the development process.) 3.测试计划(3. Test planning) 计划如何测试此增量的结果.规划测试所需的工具.你已经有工具了吗?您是否有开发所需工具的计划?(Plan how you will test the results of this increment. Plan the tools you will need for testing. Do you have the tools already? Do you have a plan for developing the tools you need?) 4.自动化(4. Automation) 花一些专用的时间构建工具来自动化您的测试过程.还计划安排时间来学习和改进测试驱动的开发技能.在时间范围内进行这些活动.每次迭代都花费少量时间来改善您的(Spend some dedicated time building tools to automate your testing process. Also plan time for learning about and improving on your test driven development skills. Time-box these activities. A small amount of time spent every iteration on improving your)**开发基础设施(development infrastructure)**加起来并为以后的迭代支付股息.值得(adds up and will pay dividends for future iterations. It’s worthwhile)**摊销(amortizing)**在项目生命周期内建设和改善开发基础设施的成本.这是非常昂贵的,并且如果一次完成所有开发,则可能需要花费数月的开发时间,因此请一次构建一下基础架构.(the cost of building and improving development infrastructure over the life of the project. This is quite expensive and it could take months of development if you did it all at once, so build out your infrastructure a bit at a time.) 5.发展(5. Development) 开发由以下紧密联系的活动组成:设计,编码和测试.单独考虑它们是不合适的.的(Development is made up of the following deeply intertwined activities: Design, coding and testing. It doesn’t feel right to consider them separately. The)**开发部分(development part)**当然,迭代的主要部分是设计,技术计划,编码和测试的每日周期.重复此过程,直到达到迭代目标为止.在这个阶段中,紧密的反馈回路非常重要.测试驱动的开发将使您专注于结果.(of the iteration, the major part of course, is the daily cycle of design, technical planning, coding and testing. This is repeated until the iterations goals have been met. It’s very important in this phase to have a tight feedback loop. Test driven development will keep you focused on the outcomes.) 6.探索(6. Exploration) 在每次迭代中保留时间仅为(In each iteration reserve time just to)**探索(explore)**产品,寻找问题.这样发现了许多问题.我们的编码人员有偏见,我们经常以(the product, looking for issues. Many problems are found this way. We coders are biased, we often write tests for the way the)**代码应该可以工作(code was supposed to work)**或针对我们期望找到的问题.但是,真正的问题往往是由玩家做意外的事情引起的.这是您的质量检查部门擅长的领域.他们会做您没想到的事情,并找到您没想到的问题.(or for the problems that we expect to find. So often, though, the real issues are caused by players doing the unexpected. This is one area where your QA department will excel. They’ll do the things you didn’t expect and find the issues you didn’t anticipate.) 7.复习(7. Review) 查看迭代结果.目标达成了吗?游戏是否符合我们测试计划设定的标准?我们遇到了什么问题?我们如何在下一次迭代中改进测试?现在是时候重新评估您的计划和方向,并考虑可以使您在下一次迭代中更加有效的流程改进.如果您正在做Scrum,这是一个(Review the results of the iteration. Were the goals met? Does the game meet the standards set by our testing plan? What issues got in our way? How do we improve on testing in the next iteration? This is the time to re-evaluate your plan and your direction and think of the process improvements that will make you more effective and efficient in the next iteration. If you are doing Scrum this is a)冲刺回顾(sprint review).(.)
测试类型(Types of Testing)
手动/重复测试(Manual/repetitive testing) 手动测试是手动遵循测试计划对软件进行缺陷测试的过程.这并不困难,也不是自动化.以这种方式开始既简单又便宜,但是随着时间的推移,成本会不断增加,就像您每次重复相同的过程一样.随着时间的流逝,您应该寻求自动化这种形式的测试.(Manual testing is the process of manually following a test plan to test software for defects . This isn’t difficult and it isn’t automated. It’s easy and inexpensive to start this way, however the costs mount over time as in session after session you repeat the exact same process. Over time you should seek to automate this form of testing.) 探索性测试(Exploratory testing) 预留时间到(Reserve time to to)**探索(explore)**您的游戏,而不是机械地贯穿测试计划.您会发现原本不会发现的问题.(your game as opposed to running mechanically through your test plan. You will find problems that wouldn’t otherwise have been found.) 重点测试(Focus testing) 将您的游戏放在目标受众的面前.他们将以您意想不到的方式使用它,并找到您不会梦想的错误.(Put your game in front of a sample of the target audience. They will use it in ways you didn’t expect and find bugs of which you won’t have dreamt.) 浸泡测试(Soak testing) 过夜运行您的游戏.一次运行几天的游戏.具有一定程度的自动化确实有助于(Run your game overnight. Run your game for days at a time. Having some level of automation really helps make this)可能(possible).您可能希望能够编写游戏的脚本或使用(. You’ll probably want to be able to script a playthrough of your game or use the)**演示(demo)**要么(or)**吸引(attract)**模式,如果有的话.确保输出帧速率和内存使用率的日志.通过绘制性能指标图表,您可以检查在测试过程中性能是否变差.(mode if you have have of those. Make sure you output a log of frame rate and memory usage. Graphing performance metrics allows you to check if performance is getting worse over the duration of the test.)
自动化测试的类型(Types of automated testing)
单元测试(Unit Tests) 代码单元在(Units of code are tested in) 隔离(isolation) .(.) 依赖注入(Dependency injection) 和(and) 嘲笑(mocking) 模拟与其他代码模块的连接.单元测试的构建成本很高,尽管使用更好的工具和更多经验会变得越来越少.至少对于您最困难和最复杂的代码而言,单元测试是值得的,这些代码必须坚如磐石.设计用于单元测试的代码会导致代码之间的松散耦合,因此以这种方式工作将对系统设计产生积极影响.(simulate connections to other code modules. Unit testing is expensive to build, although it becomes less so with better tools and more experience. Unit testing is worthwhile at least for your most difficult and complex code, the code that needs to be rock-solid reliable. Designing code for unit testing results in code that is very loosely coupled, so working this way will have a positive effect on the design of your system.) 整合测试(Integration Tests) 这类似于单元测试,除了通常将多个代码模块或系统的重要部分作为一个模块一起测试.被测代码的边界大于单元测试的边界.单元测试通常只测试一个类,而集成测试则可用于大量的协作类.(This is similar to unit testing except usually a number of code modules or a significant part of the system are tested together as one. The boundary of the code under test is larger than that for unit-testing. Unit-tests usually test a single class, integration tests work with a larger number of collaborating classes.) 集成测试更像是测试最终的(集成)系统,因为(通常)系统的任何部分都没有被仿真.它比单元测试便宜得多,因为解除了隔离带来的设计限制,这意味着您可以破解与内容紧密耦合的代码.您的代码不必设计得很好^您可能需要权衡取舍,以快速完成工作.(Integration testing is much more like testing the final (integrated) system because (usually) no parts of the system are simulated. It is far less expensive than unit testing because the design restrictions imposed by the isolation are lifted, meaning you can hack out tightly coupled code to your heart’s content. Your code doesn’t have to be so well designed… it’s a trade-off you might make to get something done quickly.) **一次性设计(Designing for disposability)**目前对我们来说很有趣.这是您设计系统各部分的地方(请考虑(is something that’s very interesting to us at the moment. This is where you design parts of your system (think)**组件(components)要么(or) 微服务(microservices) **)最终被扔出去.整个系统(零件的集成)的设计方式是,零件可以扔掉并更换,而对整个系统的影响或损坏很小.该系统将继续运行,随着时间的流逝,我们将替换整个系统.使用TDD和集成测试来构建系统的各个部分.不必太担心内部的良好设计() to eventually be thrown out. The whole system, the integration of the parts, is designed in such a way that the parts can be thrown out and replaced with little impact or damage to the system as a whole. The system continues to function and over time we replace entire sections of it. Use TDD and integration testing to build the parts of your system. Don’t worry too much about good design within the)部分(part),您打算有一天将其丢弃(, you are planning to throw it away someday, so)**骇客(hacking)**还可以(is ok.) 烟雾测试(Smoke Tests) 冒烟测试通常会测试整个完整系统(或至少其中的主要部分).这就是我们想称为的(Smoke tests usually test the entire complete system (or at least some major part of it). This is what we like to refer to as)全面测试(full build testing),因为测试将针对您的(, in that the tests are going to be run against your)**整个(entire)**游戏.这是最便宜的测试形式,但是可能很难上手.您需要能够以某种方式编写脚本或重播游戏输入.您还需要能够确定测试期间游戏的运行状况,幸运的是,如果您已经从游戏中获得了不错的日志记录和指标输出,那么这部分就不难了.然后,测试框架可以检查此输出,以验证游戏是否正在执行预期的操作.这种测试可能是广泛的,也可能只是划伤表面,任何级别的冒烟测试都会对您的游戏随着时间的推移产生巨大影响.(game. This is the least expensive form of testing but it can be difficult to get started with. You need to be able to script or replay input to your game somehow. You also need to be able to determine what the game is doing while being tested, fortunately this part isn’t difficult if you already have decent logging and metrics output from your game. This output can then be checked by the testing framework to verify the game is doing what it is supposed to be doing. This kind of testing can be extensive or it can just scratch the surface, any level of smoke testing will have a massive impact on keeping your game working over time.)
技巧(Techniques)
有许多测试技术.本节总结了我们发现有用的技术.(There are many techniques for testing. This section is a summary of techniques we have found useful.) 玩游戏(Play your game) 这似乎很明显,但这是从测试开始的地方.玩游戏(This seems obvious, but it is the place to start with testing. Play your game,)经常(frequently).(.) 测试实际版本(Test the actual build) 为了方便快捷地进行周转,您将测试在本地工作站上创建的内部版本.但是,在经过适当的游戏构建测试之前,不应将其视为完整的功能.不要只在Unity编辑器中测试它,也不要只在开发版本中测试它.与整个团队的代码和资产集成后,请确保它在构建中确实可用.(For convenice and fast turn-around you will test builds that you create on your local workstation. However, a feature shouldn’t be considered complete until it has been tested in a proper build of the game. Don’t just test it in the Unity Editor and don’t just test it in a development build. Make sure it actually works in a build after it has been integrated with code and assets from the whole team.) 如果你有一个(If you have a)**构建脚本(build script)**和/或(and/or)**持续集成(continuous integration)**系统,最终测试应该在生成的版本上进行.(system, your final testing should be done on the build that comes out of that.) 测试计划(Test plan) 制定书面测试计划.你会测试什么?预期的行为是什么?您将以什么频率测试?您将如何记录测试会议的结果?这些是您应该回答的问题.有一个过程将帮助您保持理智.(Have a written test plan. What will you test? What is the anticipated behaviour? At what frequency will you test? How will you record the outcomes of testing sessions? These are questions you should answer. Having a process will help you stay sane.) 缩短反馈周期(Shorten the feedback cycle) 确保进行更改和测试之间的往返时间尽可能短.这样可以确保测试快速有效,并且可以经常执行.使测试变得更加容易增加了您受到纪律处分并最终完成测试的可能性.拥有快速,便捷和自动化的构建过程会有所帮助.不过,您真正需要的是用于测试的自定义级别.为了测试特定功能,您需要一个缩减级别,该级别可以非常快速地加载,将游戏摄影机放置在正确的位置,并具有合适的玩家以及相关的道具和NPC,可以方便地彼此实例化.您可以采取任何措施来最大程度地减少更改前后的往返路程,直到看到更改的效果将使您更加(Make sure that the round-trip between making a change and being able to test it is as short as possible. This ensures that testing is fast and efficient and can be performed frequently. Making testing easier increases the likelihood that you will be disciplined and that testing will actually get done. Having a fast, convenient and automated build process helps. What you really need though are customized levels for testing. For testing specific features you want a cut down level that loads very quickly, has the game camera in the right position and has the right player and relevant props and NPCs conveniently instantiated near each other. Anything you can do to minimize the round trip from change, to seeing the effect of the change will make you more)生产性的(productive).(.) 资源和绩效预算(Resource and performance budgets) 您的目标是什么性能和资源使用水平?您应该了解要达到的性能特征.所需的帧速率,内存使用率,多边形数量,屏幕上的实体数量等是什么?写下来,否则您将忘记它.这样的测试相当容易自动化.(What levels of performance and resources usage are you aiming at? You should have an understanding of the performance characteristics you are trying to achieve. What is the desired frame rate, memory usage, poly count, number of entities on screen, etc? Write this down otherwise you will forget it. Tests like this are fairly easily automated.) 保持文件更新(Keep your documents updated) 我们谈论的所有文件都应视为实时文件.随着您对游戏,受众的了解以及流程的改进,使它们保持最新状态.虽然尽量不要文件太重!开发一款游戏比拥有一套完整的文档更好,但是拥有零文档也不是一件好事.(All the documents we talk about should be considered live. Keep them updated as you develop your understanding of your game, your audience and as you improve your process. Although try not to be document heavy! Having a working a game is better than having a complete set of documents, but having zero documentation isn’t great either.) 测试驱动开发(Test driven development) 通过测试推动您的开发.这是最重要的技术,是我们测试哲学不可或缺的一部分,因此我们已经进行了一定的讨论.如果可以,请创建单元测试.否则创建集成测试,它们比单元测试更易于编码和维护,但也非常有效.如果您没有时间或能力编写自动测试代码,请考虑使用TDD的原理来指导您的开发,就像我们已经讨论过的那样.(Drive your development through testing. This is the most important technique and is integral to our philosophy of testing so we have discussed it at some length already. Create unit tests if you can. Otherwise create integration tests, they are easier to code and maintain than unit tests but are also very effective. If you don’t have the time or capability to code automated tests consider just using the principles of TDD to guide your development as we have already discussed.) 输出测试(Output Testing) 从…输出有用的数据(Outputting useful data from a)**测试(test)**构建游戏是最便宜的测试方法之一,并且可以很好地转换为自动化测试.简称为(build of your game is one of the cheapest methods of testing and translates very well to automated testing. This is simply called)测井(logging).如果您登录到人类可读的文本文件,则可以直观地检查输出以验证游戏逻辑是否按预期方式运行.(. If you are logging to a human readable text file you can visually inspect the output to verify that game logic is behaving as expected.) 您可以更进一步.提交上一个(You can take this much further still. Commit previous)**日志(log)**文件到您的(files to your)**版本控制(version control)**系统,您现在可以轻松地(system and you can now easily)**差异(diff)**输出以快速了解行为是否已更改.(the outputs to quickly learn if behaviour has changed.) 您可以再走一步^将您的游戏置于自动驾驶状态(输入输入事件)并记录输出.如果在记录的输出中检测到更改,请让您的构建系统向您发送电子邮件.这是我们知道的最便宜的自动化测试方法之一,但仍然非常有效.(You can go further again… put your game on autopilot (feeding input events in) and record output. Have your build system email you if detects a change in the output that has been logged. This is one of the cheapest methods of automated testing that we know of and yet is still very effective.) 自动化(Automation) 如果您编写自动化测试,请确保计划将其频繁运行.任何体面的(If you write automated tests make sure they are scheduled to run frequently. Any decent)**持续集成(continuous integration)**系统将允许您定期或在事件(例如在(system will allow you to create builds and run tests either periodically or on events (such as on)**版本控制(version control)**承诺).(commit).) 使游戏脚本化.这并不像您想的那么难.使它能够加载一系列关卡,并使用遵循场景脚本路径的AI摄像机替换普通的玩家摄像机.或记录玩家的输入并进行回放以模拟游戏.(Make your game scriptable. This isn’t as hard as you might think. Make it able to load a sequence of levels and replace the normal player camera with an AI camera that follows a scripted path through scene. Or record player inputs and play them back to simulate game play.) 图形测试(Graphical Testing) 如果您具有完全确定的渲染器,则可以比较构建的不同运行之间的屏幕截图.像这样的程序(If you have a completely deterministic renderer you can compare screen captures between different runs of the build. A program like) **图像魔术(Image Magick)**相比(compare) 实际上使这变得容易.(actually makes this easy.) 使渲染具有确定性是另一回事.如果要完成这项工作,您需要非常专注.(Making your rendering deterministic is a different story. You’ll need to be pretty dedicated if you want to make this work.) 决定论(Determinism) 这并不是一项技术,而是您应该努力争取的技术.拥有确定性的游戏(或至少具有确定性的游戏)对于测试以及游戏开发的许多其他方面非常重要.确定性是当输入相同时从游戏中获得可预测结果的能力.换句话说,游戏应该在完全相同的条件下以相同的方式做出反应.(This isn’t as much a technique as it is something for which you should strive. Having a deterministic game (or at least as deterministic as it needs to be) is very important for testing and also many other aspects of game development. Determinism is the ability to have predictable outcomes from the game when the inputs are the same. Put another way: the game should respond the same way under the exact same conditions.) 如果您没有某种程度的确定性,那么您如何期望重现玩家或质量检查人员报告的问题?测试驱动的开发有助于改善确定性.您还需要一个可靠的随机数生成器(稍后会介绍更多内容).(If you don’t have some level of determinism then how do you expect to reproduce issues that have been reported by players or QA? Test driven development helps improve determinism. You also need a solid random number generator (more on that soon).) 关于确定性的文章,我们撰写的文章远远超出了本文的范围,因此,请继续关注有关该主题的未来文章.(We have written much more on determinism than can fit in this article, so please stay tuned for a future article on the topic.)
技术(Technology)
这是我们用来使测试更加有效的工具,技术和功能的摘要.(Here is a summary of the tools, tech and features we have used to make testing more efficient and effective.) 建立过程(Build process) 你的(Your) 建立过程(build process) 应该是自动化的,并且100%可靠且可重复.确保团队中的每个人都可以以最少的设置轻松进行构建.您应该能够从命令行运行构建,这将使通过构建自动化构建更加容易(should be automated and be 100% reliable and repeatable. Make sure everyone on the team can make a build easily and with minimal setup. You should be able to run a build from the command line, this will make it easier to automate your builds through)持续集成(continuous integration).(.) 确保开发团队都了解构建过程及其构建工具.它是(Make sure the development team all understand the build process and the tools it is built on. It is)**基本的(fundamental)**开发人员了解其工具的工作方式.他们必须具备修改和改进工具的能力,以便他们能够控制自己的工作流程.实现此目标的最佳方法是让每个开发人员都在某个时候处理构建脚本.(that developers have an understanding of how their tools work. They must be equipped to modify and improve their tools so they have control over improving their own workflow. The best way to achieve this is to have every developer work on the build script at some point.) 构建过程应该可以轻松地在CI系统和本地开发人员工作站上工作,否则您会怎么做(The build process should easily work both in the CI system and on local developer workstations, otherwise how else would you)**测试(test)**和(and)**调试(debug)**构建脚本?构建过程本身必须如此重要(the build script? It is so important that the build process itself be)经过严格测试(extremely well tested)!传统上,构建和发布充满错误.使您的构建自动化并经常进行实践,这样可以减少由于构建过程而导致构建被破坏的风险.(! Builds and release are traditionally fraught with errors. Automate your build and practice it frequently and you will reduce the risk that builds will be broken because of the build process.) 测试框架和相关库(Test framework and associated libraries) 对于单元测试和自动集成测试,您需要一个良好的测试框架和测试运行程序.您可能希望能够从命令行运行单元测试(以便可以将其包含在自动构建过程中).您还应该能够在所选的游戏引擎中运行单元测试.为此,您可能必须编写自己的测试运行程序,但这是值得的,因为某些问题可能仅在游戏引擎下运行时才会出现.(For unit testing and automated integration testing you need a good test framework and test runner. You’ll probably want to be able to run unit tests from the command line (so they can be included in your automated build process). You should also be able to run unit tests within your chosen game engine. For this you may have to code your own test runner, but it’s worth it as some issues may only show up when running under the game engine.) 在真实严肃游戏中,我们使用(At Real Serious Games we use) XUnit.net(XUnit.net) ,但这只是每一个可用的众多功能之一(, but it is just one of many that are available for every) 可能的编程语言(conceivable programming language) .为了正确隔离单元测试,您需要使用(. For proper isolation in unit-testing you’ll need to use)依赖注入(dependency injection).然后您可以使用(. Then you can use a)**嘲笑(mocking)**库来替换您的依赖项.我们用(library to replace your dependencies. We use) 起订量(Moq) .(.) 版本控制系统(Version control system) 如果你(If you)是专业的开发人员(are a professional developer)知道什么对您有好处,那么您已经在使用(know what’s good for you then you are already using) 版本控制(version control) .故事结局.版本控制对于软件开发过程非常重要,以至于很难在这么小的空间内做到公正.(. End of story. Version control is so important to the software development process that it’s difficult to do it just justice in this small amount of space.) 您应该只进行小的更改.这将使查找首次出现错误的修订版本更加容易.当您可以快速查找导致错误的更改时,错误调查会变得非常容易.这还将告诉您哪个开发人员进行了更改.与该开发人员交谈,以了解更改的意图和原因.这些都可以使您更接近该错误的修复.(You should commit only small changes. This will make it easier to track down the revision where a bug first occurred. Bug investigation can be significantly easier when you can quickly track down the change that caused a bug. This will also tell you which developer made the change. Speak to that developer to understand the intention and reasoning behind the change. This all serves to get you much closer to a fix for the bug.) 如果您的版本控制系统有一个(If your version control system has a) 二等分特征(bisect feature) 然后使用它来快速找到最新版本.一旦开始使用bisect,您会发现它会影响您的编码实践,您将开始进行编码,以便更轻松地实现bisect.(then use that to find the breaking revision very quickly. Once you start to use bisect you will find that it will influence your coding practices, you will start to code so that it is easier to bisect.) 在真实严肃游戏中,我们使用(At Real Serious Games we use either) 吉特(Git) ,(,) 水银(Mercurial) 要么(or) Perforce(Perforce) 取决于项目,团队和情况.(depending on the project, the team and the circumstances.) 错误追踪系统(Bug tracking system) 使用错误跟踪系统来记录和跟踪问题的状态.我们目前使用(Use a bug tracking system to log and track the status of your issues. We currently use) 红矿(Redmine) ,一个免费的开源解决方案.如果可能,您应该使自己更轻松,并使用单个系统进行任务和问题跟踪.我们的理由是,应该将修复错误的状态与添加功能的水平相提并论,也就是说,应根据必要性和它们为游戏提供的价值来对两者进行优先级排序.(, a free open-source solution. If possible you should make things easier for yourself and use a single system for both task and issue tracking. Our reasoning is that fixing bugs should be given a status on par with adding features, that is to say that both should be prioritized according to necessity and the value that they deliver to the game.) 差异工具(Diff tool) 您需要一种直观地检查文件之间差异的方法.您将需要检查代码修订版之间的差异,以查找或了解引入错误的修订版.您可能还想比较前面提到的输出日志(You need a way to visually check differences between files. You will need to check the differences between code revisions, to find or understand the revision where a bug was introduced. You also may want to diff output logs as mentioned earlier in)输出测试(Output Testing).(.) 我们用(We use) WinMerge(WinMerge) 和(and) 超越比较(Beyond Compare) ,但还有许多其他好的工具.(, but there are many other good tools available.) 调试工具(Debug tools) 您的游戏应记录所有重要事件.这非常适合测试,您可以直观地检查日志以验证游戏逻辑是否按预期工作.更好的是,您应该记录您的日志记录(例如,记录到文本文件或数据库中).这将允许您检查发生了什么(Your game should log all important events. This is great for testing, you can visually inspect the log to verify that the game logic is working as expected. Better yet you should record your logging (eg to a text file or database). This will allow you to inspect what happened)事实之后(after the fact),例如,您将能够进行调查(, for example you will be able to investigate)**后(after)**玩家遇到错误.日志记录对于以下形式的更高级别的自动化测试非常有用…(a player has experienced a bug. Logging is great for higher level automated testing of the following form…)
-
编写游戏脚本(如前所述)(Script your game (as mentioned earlier))
-
使用代码扫描日志以测试是否发生了某些事件.(Use code to scan the logs to test that some event has occurred.) 您的游戏应输出性能指标.您可以将它们记录到文件中,例如直接记录到(Your game should output performance metrics. You can log these to a file, for example log directly to a) CSV(CSV) 文件,并且您的指标将已经采用方便的格式加载到Excel中进行分析和绘图!更加复杂:将指标记录到数据库中,以便以后查询并用于数据分析(此时,我们必须推广开源数据分析工具包(file and your metrics will already be in a convenient format to load into Excel for analysis and graphing! Even more sophisticated: record your metrics to a database that you can later query and use for data analysis (at this point we are obliged to promote our open source data analysis toolkit) 数据伪造(data-forge) ).使用数据库意味着您可以构建一个Web应用程序以显示结果.或者更好地利用诸如(). Using a database means you can build a web app to show the results. Or better yet make use of something like) Influxdb(Influxdb) 和(and) 格拉法纳(Grafana) 记录和可视化您的效果数据.(to record and visualize your performance data.) 花时间考虑并改善游戏中的调试和可视化系统.您应该可以轻松启用和禁用整个系统.搜索问题时,请使用诸如此类的调试功能来帮助您快速缩小问题空间.在虚拟世界中,您应该能够可视化通常看不到的东西(例如力矢量).您会惊讶于某些容易解决的错误,因为您已经通过调试可视化系统看到了问题.(Spend time thinking about and improving the debugging and visualization systems in your game. You should easily be able to enable and disable entire systems. When searching for an issue use debug features like this will help you quickly narrow down the problem space. In a virtual world you should be able to visualize the things (like force vectors) that you can’t normally see. You’ll be amazed at some of the bugs that are so easily solved just because you have seen the problem through your debug visualization system.) 自动化工具(Automation tools) 您应该购买或构建自己的事件记录和回放工具.您可以记录输入事件,以便播放玩家的输入以模拟他们的游戏.您可以记录网络事件以模拟与网络播放器或服务器的交互.(You should buy or build your own tools for event recording and playback. You can record input events, so that a player’s input may be played back to simulate their game. You can record network events to simulate interaction with a network player or the server.) 您的游戏应该可以在一定程度上编写脚本.这可以像具有允许跳到特定级别然后启动事件回放或沿预先记录的路径驱动摄像机的命令行选项一样简单.更复杂:游戏可以响应网络命令(通过HTTP或套接字传递),以指示游戏开始关卡或启动事件回放.(Your game should be scriptable to some degree. This could be as simple as having command line options that allow jumping to a particular level and then initiate event playback or drive a camera along a pre-recorded path. More sophisticated: your game could respond to network commands (delivered via HTTP or sockets) that instruct it to start a level or initiate event playback.) 持续整合系统(Continuous integration system) 自动化工具本身就很好.他们可以帮助您在自己的工作站上加速该过程.但是,当在持续集成系统中自动运行构建和测试时,它们才真正发挥作用.我们用(Automation tools are good on their own. They can help accelerate the process on your own workstation. However they really come into their own when builds and tests are run automatically in a continuous integration system. We use) 詹金斯(Jenkins) 它是免费的,在软件行业中是某种标准.您可能还需要考虑许多其他选项.(which is free and something of a standard in the software industry. There are many other options that you might want to consider.) 可以使用三种主要方式来使用CI系统:(There are three main ways to make use of your CI system:)
-
每当有人对版本控制系统进行更改时,它都会构建游戏并运行测试.如果开发人员中断了构建或测试,则会自动通知团队.这可以使测试过程中的很大一部分自动化,并在游戏中断时立即提供反馈.(It builds the game and runs tests whenever someone commits changes to the version control system. If a developer breaks the build or tests the team is automatically notified. This can automate a significant part of your testing process and provides immediate feedback when the game is broken.)
-
它会按计划构建和运行测试.当游戏很大并且构建过程花费大量时间时,这是适当的.您仍然希望使用第一个选项在有人提交时运行单元测试或其他简单的快速测试,但是如果完整的构建过程很长,那么您可能只想每天进行一次完整的构建和测试.(It builds and runs tests on some schedule. This is appropriate when the game is large and the build process takes considerable time. You still want to use the first option to run unit tests or other simple fast tests whenever someone commits, but if the full build process is long then you may only want to do a full build and test once per day.)
-
它使您的同事可以自助构建和测试.团队可以随时为自己服务,并要求构建和测试.当您有许多项目或复杂的构建过程时,这非常有用(就像我们在Real Serious Games中所做的那样).并且在每次提交时或每天按计划进行构建都是不现实的.(It allows your colleagues to self-service build and test. The team can serve themselves and request a build and test at any time. This is very useful when you have many projects or a complex build process… as we do at Real Serious Games…. and it’s not practical to have them all building on every commit or on a daily schedule.) 您的CI系统将保留记录或您以前的版本,包括版本稳定性的历史记录(例如,自动测试失败的次数).当您需要了解项目的历史记录时,此信息将非常宝贵.(Your CI system will keep records or your past builds, including the history of build stability (eg the number of automated test failures). This information can be invaluable when you need to understand the history of a project.) 随机数发生器(Random Number Generator) 在游戏中拥有确定性的最简单方法之一就是控制种子(One of the easiest ways to have determinism in your game is to control the seeds to your) 随机数发生器(random number generator) .重要的是,不同的系统(例如交通,行人等)必须具有独立的隔离随机数生成器.这有助于使这些单独的系统可预测.这意味着您可以将特定系统与游戏的其余部分隔离开来,并使它们的行为相同,在研究这些系统中的问题时,可重复性非常有用.(. It’s important that different systems (eg traffic, pedestrians, etc) have separate isolated random number generators. This helps a lot to make these individual system predicable. It means that you can isolate particular system from the rest of the game and still have them behave the same way, reproducibility is very useful when investigating issues in these systems.)
统一(Unity)
让我们简短地讨论一下我们在Real Serious Games中与Unity一起使用的测试技术.(Let’s briefly discuss the testing tech we use with Unity at Real Serious Games.) 建立过程(Build Process) 在"真正的严肃游戏"中,我们的构建过程经历了多个发展阶段.它以批处理文件开始.当它变得更加复杂时,我们尝试了(At Real Serious Games our build process has gone through multiple stages of evolution. It started life as a batch file. When it got more complicated we tried) 蟒蛇(Python) .开始构建Web应用程序后,我们自然希望使用JavaScript和(. After we started building web applications we naturally wanted to use JavaScript and) 咕unt声(Grunt) 作为我们的构建系统.随着时间的流逝,构建脚本变得越来越复杂,因为我们的构建需要更复杂的准备和自动化测试. Grunt不足以管理这种复杂性(许多相互依赖的构建任务).我们尝试了(as our build system. As time progressed the build script became more and more complex as our builds required more complex preparation and automated testing. Grunt was not enough to manage this complexity (many inter-dependent build tasks). We tried) 古尔普(Gulp) 更好,但也不能满足我们的需求.(as well which is much better but also didn’t meet our needs.) 因此我们创建并开源(So we created and open sourced) 任务-(Task-Mule) ,这是我们自己的自定义自动化系统,可以处理我们现在拥有的复杂而相互依赖的构建任务网络.(, our own custom automation system that can handle the complex and interdependent web of build tasks that we have now.) 我们的CI系统和开发人员运行完全相同的构建脚本.它运行(Our CI system and our developers run the exact same build script. It runs a) Unity无头调用(headless invocation of Unity) 建立项目.(to build the project.) Unity日志(Unity Log) 的(The)**Unity日志(Unity log)**是你的朋友.这是调查问题时应首先检查错误的地方.(is your friend. It is the first place you should check for errors when investigating an issue.) 的(The)**建立日志(build log)也很有用,您需要将其连接到构建过程和CI系统中.(is also useful and you’ll want to wire this into your build process and CI system.) 如果您在构建中遇到崩溃,日志可以为您节省一些时间来跟踪问题.如果编辑器崩溃,则可能性更大.查找编辑器日志文件可能很棘手.各种平台(编辑器和构建日志)的路径都可以在这里找到:(If you experience a crash in a build, the log can save you some time tracking down the issue. If the Editor crashes, this can be even more likely. Finding the Editor log file can be tricky. The paths for the various platforms, both editor and build logs, can be found here:) http://docs.unity3d.com/Manual/LogFiles.html(http://docs.unity3d.com/Manual/LogFiles.html) .(.) 倾卸系统信息(Dumping System Info) 将系统信息记录到文件系统.可以通过Unity的系统信息检索系统信息(Log system info to the filesystem. System info can be retrieved through Unity’s) SystemInfo类(SystemInfo class) .如果您在PC上发布,则可以使用(. If you publish on the PC you can make use of the) DxDiag命令(DxDiag command) 了解用户的系统.有时,您会遇到在特定平台,系统或硬件上出现的问题.在这些情况下,了解您的用户正在运行哪个系统非常宝贵.(to understand a user’s system. Sometimes you will have issues that manifest on particular platforms, systems or hardware. In these cases it is invaluable to understand what system your users are running.) 单元测试(Unit Testing) 如今,Unity的测试框架是(These days Unity has a testing framework that is) 在资产商店中可用(available on the asset store) 适用于Unity 4.0及更高版本.在5.3版中,Unity测试运行器内置在Unity Editor中.这看起来确实很有用,但是当我们开始使用Unity时,此功能不可用.我们用(for versions of Unity 4.0 and higher. In version 5.3, the Unity test runner comes built into the Unity Editor. This looks really useful, but when we started using Unity, this wasn’t available. We use) 单位(xUnit) 编写我们的测试(to write our tests and) 起订量(Moq) 嘲笑.我们使用(for mocking. We use the) RSG工厂(RSG Factory) 用于依赖注入.(for dependency injection.) 我们在Visual Studio中的XUnit测试运行器下运行测试.我们还有一个手动编码的测试运行程序,可以在Unity下运行测试.为什么这有用?这意味着我们可以验证我们的代码是否可以在普通.NET框架以及Unity的Mono框架下正常工作.有时两者之间的差异可能会导致问题.在Visual Studio中运行单元测试既快捷又方便,但这不能保证在Mono下使用相同的代码,因此请同时进行测试.(We run our test under the XUnit test runner in Visual Studio. We also have a hand-coded test runner to run our tests under Unity. Why is this useful? It means we can verify that our code works under the normal .NET framework and also under Unity’s Mono framework. Sometimes the differences between the two can cause problems. It’s fast and convenient to run your unit tests in Visual Studio, but this is no guarantee that the same code will under Mono, so please test both.) 有了Moq,我们可以创建(With Moq we can create) 嘲笑(mock) **对象以模拟单元测试的依赖关系.当处理没有接口或虚函数的Unity类时,这显然会带来问题.我们使用一个简单的抽象层来模拟Unity API,尽管这提供了一个不理想的间接层,并且我们正在研究可能在以后的文章中写到的替代方法.(objects to simulate dependencies for unit testing. This obviously presents problems when dealing with Unity classes that don’t have interfaces or virtual functions. We use a simple abstraction layer to make it possible to mock the Unity API, although this gives a layer of indirection that isn’t ideal and we are investigating alternatives that we might write about in a future article.) 持续集成(Continuous Integration) 我们用(We use) 詹金斯(Jenkins) 为我们的持续集成服务. Jenkins监视代码存储库(通常(for our continuous integration services. Jenkins monitors the code repository (usually) 水银(Mercurial) ),并在存储库发生更改时执行构建并运行测试.(), and performs a build and runs tests when there have been changes to the repository.) 我们的Unity项目(通常(Our Unity projects (usually) Perforce(Perforce) )也是通过詹金斯建立的.这些构建通常是由自助服务触发的,尽管我们的某些构建也按夜间计划进行.() are also built through Jenkins. These builds are usually triggered by self-service, although some of our builds are also on a nightly schedule.) 测井与遥测(Logging and Telemetry) 日志记录是一种非常有价值且非常简单的测试工具. Unity具有内置(Logging is a valuable and surprisingly simple tool for testing. Unity has a built in) 记录API(logging API) 可以帮助您入门,但要推出自己的系统要灵活得多,实际上并没有那么困难.我们的日志记录系统基于.NET 3.5端口(that will get you started, but it’s really not that difficult to roll your own system that is so much more flexible and powerful. Our logging system is based on the .NET 3.5 port of) 塞里洛格(Serilog) .(.) 我们还编写了各种支持工具来帮助我们监视实时日志记录和查询存储的日志记录.的(We have also written various supporting tools to help us monitor live logging and query stored logging. The) 日志服务器(LogServer) 是一个微型的node.js服务器,它通过HTTP接受日志并将其存储在(is a tiny node.js server that accepts logs via HTTP and stores them in a) MongoDb数据库(MongoDb database) .的(. The) 日志查看器(LogViewer) 从数据库中读取日志,并将其显示在网页中.使用此系统,我们可以非常方便地将来自多个版本,不同设备甚至不同平台的日志流聚合到一个可搜索的系统中.(reads the logs from the database and displays them in a web page. With this system we can very conveniently aggregate log streams from multiple builds, different devices and even different platforms into a single searchable system.) 我们的(Our) 指标体系(metrics system) 与我们的日志系统类似.我们可以将事件和数据输出到(is similar to our logging system. We can output events and data to) 服务器(server) 它们存储在数据库中的位置.这对于了解我们的帧速率和其他随时间推移的指标非常有用.我们可以测量设备温度,内存分配,玩家位置和方向以及可以打包到设备中的任何其他值(where they are stored in a database. This is invaluable for understanding our frame rate and other metrics over time. We can measure device temperature, memory allocation, player position & direction and any other values that can be packed into a) JSON格式(JSON) 有效载荷.(payload.) 由于日志和指标存储在数据库中,因此我们能够查询和检查来自先前应用程序实例的数据.记录问题后,能够查询数据库以获取信息非常强大.我们可以回到过去,分析该玩家会话期间发生的情况.该系统可以远程操作的事实意味着我们可以理解我们的用户及其所处位置的问题.时间和距离不再是过去的障碍.(Because logs and metrics are stored in a database we are able to query and inspect data from previous application instances. It is so powerful to be able to query a database for information after an issue has been logged. We can go back in time and analyze what happened during that player’s session. The fact that this system operates remotely means we can understand our users and their issues wherever they might be. Time and distance are no longer the barrier that they used to be.) 如果您对使用Serilog for Unity感兴趣,请查看.NET 3.5分支.(If you are interested in having Serilog for Unity please check out the .NET 3.5 branch of) 灰的叉子(Ash’s fork) .请注意,尽管让这样的代码在Unity下工作是绝技,只能由受过训练的专业人士执行,但不要在家里的孩子身上尝试.(. Please be warned though that getting code like this to work under Unity is a stunt that should only be performed by trained professionals, don’t try this at home kids.) JSON序列化(JSON serialization) 您可能需要一个好的JSON序列化程序来满足常规的序列化需求.拥有JSON序列化程序对于捕获事件(以供稍后播放)和(You’ll probably need a good JSON serializer for your general serialization needs. Having a JSON serializer is also useful for capturing events (for later playback) and)**输出测试(output testing)**前面提到过. Unity 5.3(最终)附带(that was mentioned earlier. Unity 5.3 (finally) comes with) 自己的JSON序列化器(its own JSON serializer) 我们想尽快尝试.迄今为止,我们已经使用了JSON.NET.很棒,但是很难在Unity下工作.你可以找到一个(that we’d like to try out soon. To date we have used JSON.NET. It’s fantastic but can be difficult to get working under Unity. You can find a) 在Unity下工作的叉子(fork that works under Unity here) ,尽管我们听说这在iOS下不起作用.(, although we have heard this doesn’t work under iOS.) 随机数生成(Random Number Generation) 您可以设置(You can set the) 种子(seed) 对于(for) Unity的随机数生成器(Unity’s random number generator) .这是进行确定性游戏的良好开端.不幸的是,尽管该系统是全局系统,所以必须将一个随机数流共享给所有系统.这可能会导致系统相互干扰并导致不可预测的行为.这意味着您无法有效隔离系统(例如,您无法拔出自己的系统(. This is a good start for having a determinstic game. Unfortunately though this system is global and so a single stream of random numbers must be shared out to all of your systems. This can lead to systems that interfere with each other and cause unpredictable behaviour. That means you can’t isolate your systems effectively (for example you can’t pull out your)**行人(pedestrians)**系统,并使其具有相同的行为).(system and have it behave the same way on its own).) 在真实严肃游戏中,我们使用(At Real Serious Games we use) SimpleRNG(SimpleRNG) 生成我们的随机数.(to generate our random numbers.)
结论(Conclusion)
在本文中,我们介绍了应用于游戏开发的软件测试.这真的是(In this article we have covered software testing as applied to game development. This is really just)**软件测试(software testing)**量身定制,以满足我们游戏开发人员的需求.(tailored as we see fit to the concerns of game developers.) 您已经了解了我们的测试理念以及可以使测试工作的一些技术.尽管此处讨论的测试技术可以与任何语言或游戏引擎一起使用,但我们已经展示了其中的一些技术如何应用于Unity.(You have learned about our philosophy of testing and some of the techniques and technologies that can make testing work for you. Although the testing techniques discussed here can be used with any language or game engine, we have shown how some of them apply to Unity.) 我们希望您现在处于更好的测试状态,并且能够体会测试的价值.至少我们会让您更多地考虑它.在最好的情况下,您现在可以翻转整个开发过程,并通过测试前端和中心来推动它前进.(We hope you are now in a better position to test and can appreciate the value of testing. At the very least we will have made you think more about it. In the best case you can now flip around your entire dev process and drive it forward with testing front and center.) 如果您没有从本文中除其他外,请记住以下几点:(If you take nothing else away from this article, remember these things:)
- 测试无法结束.这样做会延迟并在项目结束时积累风险,在项目结束时可能造成最大的损失.(Testing can’t be left to the end. Doing so delays and accumulates risk to the end of the project where it can do the most damage.)
- 测试将帮助您交付高质量的游戏,该游戏可以按预期运行,没有重大问题并且可以在性能限制内运行.(Testing will help you deliver a high-quality game that works as intended, has no major issues and works within performance constraints.)
- 测试驱动的开发可以(可能应该)指导您的开发并极大地改善您的过程(我们不只是在谈论单元测试!).(Test driven development can (and probably should) guide your development and vastly improve your process (and we aren’t just talking about unit tests!).) 最后…(And finally…)只是做一些测试(just do some testing).(.)
关于作者(About the Authors)
阿什莉`戴维斯(Ashley Davis)(Ashley Davis)
Ash是一位经验丰富的软件开发人员,自1998年以来一直从事专业游戏开发,在其他行业中有一些涉猎. Ash现在在以下位置构建严肃的游戏,模拟和VR体验(Ash is an experienced software developer and has been developing games professionally since 1998 with a few interludes in other industries. Ash now builds serious games, simulations and VR experiences at) 真正的严肃游戏(Real Serious Games) . Ash也是这个名字的承包商(. Ash is also a contractor under the name) 代码雀跃(Code Capers) 并开发了跨多个平台的产品.(and has built products that span multiple platforms.) Ash为开源社区做出了贡献,并且是Ash的创始人和组织者(Ash contributes to the open source community and is a founder and organiser of) 游戏技术布里斯班(Game Technology Brisbane) 和(and) 游戏开发布里斯班(Game Development Brisbane) .灰还有助于组织(. Ash also helps out organising) 布里斯班Unity开发人员(Brisbane Unity Developers) .(.) 对于更长的生物,请参阅Ash的个人资料(For a longer bio please see Ash’s profile on) 链接到(linked in) .(.)
亚当`辛格(Adam Single)
亚当是一位热情的游戏开发商. Adam是前RSG,现在是Well Placed Cactus开发团队的高级成员.他是布里斯班游戏技术,布里斯班游戏开发和布里斯班Unity开发人员聚会的组织者.(Adam is a passionate game developer. Adam is ex-RSG and now a senior member of the Well Placed Cactus development team. He’s an organiser for Game Technology Brisbane, Game Development Brisbane and Brisbane Unity Developer meetups.) 他还是一个名为OneCoin Creations的小型两人团队的联合创始人.作为父亲,他们适合在工作和家庭生活之间发展自己的游戏.(He’s also the co-founder of a small, two man team called OneCoin Creations. As fathers, they fit the development of their own games in between work and family life.) 有关更多信息,请参见:(For more info please see:) https://branded.me/adamsingle(https://branded.me/adamsingle)
关于审稿人(About the Reviewers)
非常感谢我们的评论员,他们帮助使本文变得真实.(A big thank you to our reviewers who have helped make this article what it is.)
马克`霍本(Mark Hogben)
马克(Mark)是一位专业的软件工程师,拥有16年以上的经验,其中大部分是游戏行业的经验.他目前正在从事自己的游戏项目,并撰写了第二本小说.(Mark is a professional software engineer with over sixteen years experience, most of which has been in the games industry. He is currently working on his own game projects, and writing his second novel.)
利`曼尼斯(Leigh Mannes)
Leigh是放置良好的仙人掌的技术负责人.在为全球的代理商和机构从事移动,在线和现实世界的体验式安装工作十多年之后,他加入了该团队.(Leigh is the technical lead for Well Placed Cactus. He joined the team after more than a decade working across mobile, online and real-world experiential installations for agencies and institutions around the world.) http://bearstoxicchemicals.com/(http://bearstoxicchemicals.com/)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
QA Dev 新闻 翻译