目前,我们只在夹具级别实现了并行执行。 应该可以并行运行夹具的各个方法以及参数化方法的各个测试用例。
我们应该能够在夹具或方法上指定精确的并行级别。
这个问题以前是 #66 的一部分
更新:此评论和以下评论都是对显然删除自己评论的个人的回复。 我要留下我的答案。
嗯,它在规范中并计划在 3.0 之后实现。 如果它那么容易,我们可能会做到。 不确定您看到的与 mbunit 的连接。 他们拥有它的事实对我们没有帮助。
这有点令人厌烦。 几点,已经说明但显然错过了......
我发现你关于“逆向工程”的谈话非常令人不安。 开源只有在尊重版权的情况下才有可能。 因此,如果您建议我们可能忽略 mbunit 许可条款,那您就离谱了。
虽然我确实为 MbUnit 贡献了许多补丁并使用它多年,但我
从来都不是主要贡献者。 我不希望我的身份被误传:)
至于逆向工程,这里真的没有任何用处。 NUnit 工作
与 MbUnit 完全不同。 我们将在适当的时候解决这个问题,
但正在谨慎地接近它,因为其他类似的问题可能会改变
我们需要的方式来实现这一点甚至冲突。
2015 年 4 月 19 日凌晨 2:45,“CharliePoole”通知@github.com 写道:
这有点令人厌烦。 几点,已经说明,但
显然错过了...1.
有一个计划来实施您的要求。
2.我们决定作为一个团队在某个时间安排它。
3.何时安排主要与我们对
与其他特征相比,该特征的价值。
4.NUnit 团队中有几个人可以实现
特征。
5.他们将能够根据优先级实施它
他们的头脑,不需要从任何地方复制它。我发现你关于“逆向工程”的谈话非常令人不安。 开源是
只有在尊重版权的情况下才有可能。 所以如果你是
暗示我们可能会忽略 mbunit 许可条款,您离我们太远了
根据。—
直接回复此邮件或在 GitHub 上查看
https://github.com/nunit/nunit/issues/164#issuecomment -94244650。
一个比我更委婉的评论!
我们目前在并行执行领域的优先事项是:
这似乎代表了对用户最有用的顺序。
我还要提一下,将某些内容标记为 3.0 后并不一定意味着该功能比我们将其作为 3.0 的一部分来得晚。 相反,这可能意味着 3.0 来得更早。
当我们这样做时,我们将不得不决定如何处理设置和拆卸命令。 最简单的选择可能是为每个测试构建测试类,以便不存在数据争用。
无论如何,我希望在某个时候将其作为一个选项,但我不确定它是运行选项还是固定装置(归因)选项或两者兼而有之。
你好!
将此功能添加到 NUnit 的下一个版本会很棒,因为它是唯一阻止我切换到 NUnit 的东西。 是否仍计划在 3.4 中使用此功能?
@julianhaslinger NUnit 3.4 将在本月底发布,所以不,不会包含此功能。
仅供参考,这个问题在我们的待办事项里程碑(或伪里程碑)而不是 3.4 中,因为我们遵循的做法是提前向每个编号的里程碑添加少量关键定义问题。
下一个里程碑 3.6 计划在 3 个月后发布,这可能让您感到沮丧。 :-( 但是,如果您看到此问题已合并到 master,您将能够从我们的 MyGet 提要中获得更早的下降。
@julianhaslinger这不会出现在 3.4 中,它可能会在一周多后发布,但我希望尽快完成,所以您的投票会有所帮助:+1:
顺便说一句,您正在使用哪个支持并行方法执行的测试框架? 我认为XUnit 也只允许并行运行测试到类级别。 我错了吗? 我不怎么使用 XUnit :smile:
@CharliePoole感谢您的回答! 好吧,虽然这听起来有点令人沮丧。 但是,我会等待下一个版本(或更早的版本)。 请(仍然)在下一个版本 (3.6) 中考虑此功能。
@rprouse我现在正在使用 MbUnit/Gallio。 该项目几乎死了,现在我要切换到 NUnit。
@julianhaslinger对你来说是跑步时间的问题吗? 你有关于夹具内测试用例分布的一些数字吗? 我问是因为我的假设是,除了他们从并行装置中获得的东西之外,该功能几乎没有给用户带来什么。 如果这是错误的,它可能会改变其相对优先级。
@CharliePoole没错,我们的实际问题是测试用例的运行时间。 我们想将 NUnit 用于我们的自动化/回归测试(包括 Selenium/WebDriver),并且由于我们的一些测试类有 200 多个测试用例,目前使用 NUnit 执行整个测试套件确实很痛苦。
比较(在我们的回归测试的较小测试集中)表明,可能的 NUnit 解决方案将在大约 1.5 小时内执行,而当前的 MBunit 解决方案将在 0.5 小时内执行(相同的测试集)。
但是, @CharliePoole ,我知道我们可以通过将较大的测试类拆分为较小的类来减少执行时间,但这会以某种方式破坏我们测试类层次结构的最初想法。
@julianhaslinger - 只是确认一下,您确定您的运行时间受 CPU 限制,而不是内存限制吗?
当我们第一次尝试切换到 NUnit 3 时,我们遇到了同样的问题 - 运行时间明显变长了。 这是由于 NUnit 将可用内存最大化了 - 当前版本存在一个问题,它会保留所有测试对象,直到测试运行完成。 我们目前正在内部运行修补版本 - 我想获得 3.4 的 PR,但不确定此时我是否有时间。 :-(
抱歉,如果不是这样,但认为值得一提,因为 Selenium 可以使用它的公平份额内存。 :-)
@ChrisMaddock感谢您的输入! :+1: 我们很快就会看一看,然后我会回来找你。
@ChrisMaddock我很想在 3.4 中看到您的内存修复。 如果您想提出 PR,如果它尚未准备好用于生产,我们可以帮助您清理它:+1:
@rprouse - 这个初始提交https://github.com/nunit/nunit/pull/1367/commits/5f98ae51025f7af8244abd4367d1f47260874dfc在 PR #1367 中为我们正确释放了一些东西,在一个补丁 v3.0.1 中。
你会在 PR 中看到它在合并之前被移到了OneTimeTearDown
- 我还不知道这个移动是否导致它在 v3.2.1 中不起作用,或者是否有另一个改变工作重新引入了保留 - 我很可能在搬家后没有重新测试。
将尝试重新测试它并在明天抛出它,这对我们回到核心版本也很好。 :-)
@ChrisMaddock我查看了回归测试运行期间的内存消耗,发现测试运行的执行不受内存限制。 我想我们真的必须等待一个 NUnit 版本,它可以处理每个类中各个方法的并行执行。
只是为了补充@julianhaslinger所说的,我在使用 NUnit 和 Selenium 测试时看到了完全相同的问题。 我必须编写一个自定义包装器,针对从传入的程序集中刮取的单个测试运行 nunit-console.exe 的单个实例,以便我现在可以运行并行测试。 这并不理想,因为它导致生成许多 .xml 输出文件(每个测试运行一个)而不是单个 .xml 输出,这也意味着我不能使用 _OneTimeSetUp_ 和拆卸方法,而必须依赖外部信号量和环境变量来控制我只想运行一次的执行流程。 很长一段时间以来,我一直遵循在 NUnit 中并行执行的承诺,并且对该功能在 3.0 中的推出方式感到非常失望(仅部分支持,需要对问题和发行说明进行一些真正的挖掘以发现并非所有内容都得到实际支持)。 我什至自己调查了推动这一进程所涉及的内容,但不幸的是,NUnit 的设计似乎与测试方法级别的并行执行的实现背道而驰,我不知道您实际上会喜欢什么处理潜在的非线程安全代码(即应该留给并行使用 NUnit 的人以确保所有测试方法以线程安全的方式正确引用任何外部,还是 NUnit 本身应该处理其自己域中每个方法的执行,同时以某种方式尝试仍然只运行一次性设置和拆卸类型的方法一次)并且因为我已经有了一个解决方法,所以我无法证明自己实现这个功能的时间(这可能是最好的,因为我之前已经被烧毁了与 GitHub 上的团队合作,帮助他们实现并行执行)。 无论如何......抱歉散漫......我知道C#代码的单元测试的优先级可能不太依赖方法级并行性,但请知道对于我们这些使用NUnit进行基于Selenium的测试的人这将是一个巨大的改进。 提前致谢! :微笑:
感谢您的意见。 我想我会在这里闲聊一下......
它有助于了解人们需要什么以及他们为什么需要它。 我自己不是 Web 开发人员,我尝试倾听 Selenium 用户的意见并专注于他们想要的东西。 这似乎是在测试用例之间进行排序的并行装置。 我完全理解不同的人会想要不同的东西,但是当这两个群体都表达“Selenium 用户需要什么”时,这有点令人困惑。 您能否为我概述哪些类型的 Web 测试可能需要方法级并行性,而不是那些希望以预定义顺序运行方法的人? 我想我可以猜到,但我宁愿从用户那里得到它。
关于您的解决方法……您是否考虑过使用单独的测试程序集? NUnit 很乐意在单独的进程中并行运行每一个。 当然,这并不能消除同步访问文件等内容的需要。
关于线程安全 - 我们从未计划让我们的并行实现负责线程安全。 我唯一希望保证的是,如果您的方法已经是线程安全的,则 NUnit 不会产生任何线程安全问题。 事实证明,这本身并不重要。
感谢您的回复。 我完全理解你的评论
在夹具中对测试执行进行排序并将测试拆分为单独的
组件。
我已经是 NUnit 用户并且已经使用了多年(以及之前的 JUnit)
所以依靠夹具中的测试顺序的想法甚至不是
在我的测试设计中考虑。 每个测试都试图成为一个完全封装的
站点内的操作或一组操作,不期望顺序
执行。 我正在测试的站点的设计也意味着许多测试
最多可能需要 20 分钟才能执行(其中大部分时间都花在等待
发生在网站上的事情)并且测试类型涵盖
多个相似的场景,因此使用基础测试类来减少代码
通过使用公共基类的方式进行复制和提高可维护性
方法。 测试被组织成基于开发的单独项目
该区域的团队所有权(因此我们确实使用单独的程序集,但是
每个程序集有很多测试,我的测试包装器将处理
所有测试中的所有测试都与之前创建的程序集并行传递
NUnit 3 的第一个正式版本,我想确保所有测试都有
在给定足够线程的情况下同时执行的可能性
可用的)。
本质上,您可以想象一个程序集可能有 10 个测试和
另外 100 个测试,但 10 个组件的测试需要 10 分钟
每个而具有 100 个的程序集每个测试需要 1 分钟。 如果我
拥有一台能够运行 110 个并行线程的机器(实际上是
我们基础设施设计的一部分)然后我希望测试完成
在 10 分钟内,而不是在 100 分钟内。
希望这有助于解释...对不起,如果事情仍然不完全清楚,
但总体而言,方法级别的并行性是我所拥有的
在其他测试库(例如 ruby 中的 prspec)中看到缺失以及何时
通过添加它来分析性能改进我
发现这可能是一个重大的积极变化。 请参阅以下示例:
https://github.com/bicarbon8/rspec-parallel/wiki/Examples
2016 年 7 月 1 日 00:45,“CharliePoole”通知@github.com 写道:
感谢您的意见。 我想我会在这里闲聊一下......
它有助于了解人们需要什么以及他们为什么需要它。 不是一个
我自己是 Web 开发人员,我尝试听取 Selenium 用户的意见并专注于什么
他们想。 那似乎是带有订购功能的平行装置
在测试用例中。 我完全理解不同的人会想要
不同的东西,但是当两个群体都表现出表达
“Selenium 用户需要什么”这有点令人困惑。 你能帮我概述一下吗
什么样的网络测试可能需要方法级的并行性而不是
那些想要按预定义顺序运行方法的人? 我想我可以
猜测,但我宁愿从用户那里得到它。
关于您的解决方法...您是否考虑使用单独的测试
大会? NUnit 很乐意在一个单独的地方并行运行每个
过程。 当然,这并不能消除同步访问的需要
文件之类的东西。
关于线程安全 - 我们从来没有计划我们的并行实现
负责线程安全。 我唯一期待的
保证 NUnit 不会_创建_任何线程安全问题,如果你
方法已经是线程安全的。 事实证明,这本身并不重要。
—
您收到此消息是因为您发表了评论。
直接回复本邮件,在GitHub上查看
https://github.com/nunit/nunit/issues/164#issuecomment -229819324,或者静音
线程
https://github.com/notifications/unsubscribe/ACNsyoczCUV9L7kbF2SHB7lLsyBKlrv9ks5qRFUJgaJpZM4CUZ8r
.
感谢您提供的信息……看到各种观点很有帮助。
我的5美分。
在我们的项目中,我们有大约 25 个测试程序集,并且每个程序集和每个夹具的测试并行测试执行已经大大减少了执行时间。 在夹具中并行执行测试将进一步改进它。 现在我们甚至将最耗时的fixtures 拆分成几个fixtures 以加快执行速度,但是如果nunit 并行运行fixture 测试会好得多。
我真正想在 nunit 中看到的是测试用例级别的测试并行化,因为将此类测试拆分为固定装置并不总是很方便,并且会导致代码重复。 我们有几个测试可能需要多达数千个测试用例(每个用例执行速度很快,但总共需要几分钟)或只有几十个用例(但每个用例都很慢),目前此类测试主要用于我们。
感谢您的输入...这是我们将在下一个版本中解决的一个领域以及确保某些测试不会彼此并行运行的竞争但互补的问题!
我之前的问题更多是关于人们如何编写测试,尤其是在驱动 Web 应用程序时。 有些人坚持他们希望每个方法都是一个有序的步骤,而夹具代表一系列这样的步骤。 这当然是不平行的定义。 其他人似乎编写了非常相似的测试,而没有对测试进行排序。 我的猜测是后一组编写更大的测试方法,每个方法都有一系列动作和断言。
@CharliePoole好消息! 非常感谢!
在我看来,测试用例应该是孤立的,而不是依赖于其他测试用例或执行顺序。 如果人们仍然想单线程运行一些测试,他们仍然可以使用 [Parallelizable(ParallelScope.None)] 和/或 OrderAttribute。
与本地 webdriver 网格或 Saas 提供商(如 BrowserStack 或 SauceLabs)相比,正在实施的此问题将允许更快地运行测试套件。 目前,我尝试将测试类上的测试方法数量限制为可用的 webdriver 节点或浏览器会话的数量,以便充分利用网格。 否则,如果一个测试有 8 个测试方法,而我的网格有 8 个浏览器会话可用,则只会使用一个,因为该类的所有测试方法将一次运行一个。
@pablomxnl绝对同意。 作为教练或项目负责人,我一直非常努力地推动这个想法。 但是,我在这里没有戴任何一顶帽子。 我是一个软件供应商,用户要求东西。 如果他们要求真正令人震惊的东西,我只会说不。 但是,如果他们要求在某些情况下合理的事情,而不是其他情况——甚至不是大多数——我会考虑。
就网站而言,我们几乎总是不谈论单元测试。 更高级别的功能测试通常需要排序。 无论是通过测试中的一组步骤还是一系列方法来完成,对我们来说都是一个实现细节,对用户来说是一个方便的问题。 就个人而言,我认为我们可能需要位于 [StepFixture] 类中的名为 [Step] 的东西,或一些类似的名称,以便我们可以将所有这些排序/排序的东西从单元测试中移走。 也许我会在网络消亡之前有时间做这件事。 :-)
无论如何,了解人们如何实际使用您的软件总是很有趣的。
@CharliePoole ,请不要误会我这个问题(只是想确定一下):此功能是否会添加到下一个版本(
虽然我可以假装预测未来,但那只会让你满意到九月。 :-)
让我通过解释我们如何“安排”功能来回答。
我们目前正在尝试(从年初开始)一种每季度发布一次的方法。 随着我们在发布方面做得更好,我们可能会加快步伐。 最终,我们或许能够进行持续部署。
在志愿开源项目中,每个月没有固定的可用工作量。 我们可以使用“昨天的天气”方法,但事实证明,人们必须在 NUnit 上花费的时间以及志愿服务的人数变化很大。
作为妥协,我们选择了少量对发布至关重要的问题,并提前将它们添加到里程碑中。 我的偏好是添加不超过我们希望完成的大约 25%。 发布中的大多数问题仅在完成后或充其量有人承诺处理它们时才会添加到该里程碑。 如果没有人指派给他们,你通常不会在我们的 3.5 里程碑中找到未解决的问题,尽管我偶尔会这样做,如果它看起来像阻碍了其他工作。
因此,我们所做的积极的一面是我们几乎可以保证发布会按时发布。 不利的一面是我们无法告诉您其中会包含什么。 :-(
对于这个特定的问题...我已将其置于高度优先级以告诉我们的开发人员它很重要。 必须有人可以自由地工作,并且有足够的背景来完成这种范围和难度的项目。 如果有合适背景的人在接下来的几周内接受了这一点,我想这可以通过发布来完成。 作为指导方针,我认为我需要大约一个月的时间,同时还要处理其他一些事情,才能通过我的方式解决这个问题。
抱歉,没有更明确的答案,但这样的答案必然是谎言!
@CharliePoole是否有任何更新考虑到此功能?
@tomersss我们还没有开始工作,3.5 有望在几周内发布,所以它不太可能出现在下一个版本中。 我们希望尽快添加此功能,但本周我们一直在忙于重组我们的存储库和代码库。 虽然它被标记为高优先级,所以它在我们的雷达上。
@CharliePoole这个问题有什么更新吗?
@KPKA我们还没有开始工作,所以没有更新。 对于安装了 ZenHub 的用户,您会看到这个问题从待办事项转移到待办事项,然后在我们开始处理时进行中。
对于 Zenhub 的非用户,您将能够通过查看分配给问题的人员来判断有人何时拿起它。
@CharliePoole @rprouse
你好!
有没有关于这个问题的消息?
是在下一个版本中发布,还是计划在即将到来的里程碑之一中发布?
目前这是阻止我们切换到 NUnit 的唯一问题。
如果有人可以承认自己在不久的将来开始从事这项工作,那将会很友好,因为我猜有很多人受到影响。
希望早日收到你的消息
@GitSIPA你在使用什么测试框架来允许你并行运行测试方法?
为了回答你的问题,没有人开始研究这个问题,所以没有 ETA,但我们会在决定下一步工作时考虑你的投票。
+1,同意@GitSIPA。 这是非常重要的功能
@GitSIPA +1
@rprouse我们正在使用 mbunit,但现在不支持此框架。 我们在 mbunit 方面有一些问题。
@rprouse我们目前也在使用 MbUnit,但由于不支持新的 Visual Studio 版本,我们考虑切换到 NUnit。
在问题 #1921 @jnm2 上问“我们和参数化测试用例并行运行之间有什么关系?我可以做出贡献吗?”
首先第二个问题:当然! 我们很乐意得到您的帮助。
对于第一个问题:
我们执行“WorkItems”,它当前一对一地映射到测试。 我认为我们需要将夹具的 OneTimeSetUp 和 OneTimeTearDown 视为单独的 WorkItem 作为初步步骤。 问题 #1096 处理这个问题。
我们需要有一些方法让一个 WorkItem 依赖于其他 WorkItem,这样它只会在所有依赖项都完成时才被安排执行。 我们目前使用 CountDown 以一种非常简单的方式来做到这一点,但我们需要更通用的东西。 当然,第一个用途是让 OneTimeTearDown 依赖于所有测试的完成。 当我们在测试之间实现依赖时,它会有其他用途。 我把它想象成一个待处理的工作项队列,但可能还有其他方法来实现它。
解决这两件事后,我们可以开始解决主要问题本身:安排测试运行,而不是在为夹具执行 OneTimeSetUp 的同一线程上运行它们。
如果您想从事此工作,您必须非常熟悉 NUnit 实际如何分派执行测试的一些内部结构。 我很乐意帮你做到这一点。
目前做了哪些规划?
我的需要是并行运行足够多的 TestCaseSource 案例以使 CPU 饱和。 我没有设置、拆卸或订购要求。 其他人将需要考虑这些。
我希望 TestCaseSource 执行是并行化的,因此同一夹具中使用不同 TestCaseSource 的两个方法将并行执行枚举。 如果两个方法使用相同的 TestCaseSource 并且只执行一次,这似乎会很好 - 对此有想法吗?
编辑:评论比赛条件。 我们已经有了一个好的开始! 😆
我要重复一个我最近不得不讲的故事。 :微笑:
NUnit 首先加载测试(又名发现、探索),然后根据运行器的类型执行一次或多次。
您的 TestCaseSource 用于加载测试,而不是运行它们,我们甚至不将其视为测试的一部分 - 尽管您可能将其与测试在同一个类中。
IOW,您的测试用例不会“使用”您的测试用例源,而是 NUnit 使用源来创建测试用例。 当然,在创建之前它们不能做任何事情。 有道理?
碰巧的是,从源创建测试是按顺序完成的。 如果您在源代码中执行了一些导致问题的代码,我的第一个猜测是您在测试用例源代码中做了太多事情。 例如,您不想在测试用例源中创建类的实例,而是想存储将用于创建它们的参数。 不幸的是,这可能是一整本书的章节。 :微笑:
所以,这个问题是关于 __running__ 并行测试用例。 这意味着夹具下的所有测试用例,除非您将某些测试用例标记为不可并行化。 简单的非参数化测试以及参数化测试的个别情况在此将被同等对待。
允许在没有 OneTimeTearDown(我认为 OneTimeSetUp 是可以的)的装置中并行化测试将是一个有趣的实验。 如果你能正确地做出这个决定,它可能很容易工作。 然而,确定比您想象的要困难,因为 OneTimeTearDown 可以包含继承的方法和全局 ActionAttributes。
@jnm2您是否已经有机会解决这个特定问题?
@julianhaslinger不。在我的两个更直接的问题之后,1885 年和 1933 年,它在我的名单上。如果你想解决它,那就更好了!
@julianhaslinger由于我们彼此不认识,请原谅我说这是一个很难接受的问题。 确保你深入了解事情现在是如何完成的以及为什么 - 恐怕后者并不总是显而易见的。 请参阅我在https://github.com/nunit/nunit/issues/164#issuecomment -265267804 上的评论,了解我希望看到的单独 PR 的细分,以解决此问题。 如果你想出一个更简单的方法,在编码之前发布它,这样我们就可以权衡未来的考虑与预测未来所涉及的明显 YAGNI。
@CharliePoole @jnm2 大家好!
我并不是想开始实现这个缺失的功能,而只是想了解它的进展。 正如我从您的回答(以上)中可以看出的那样,此特定功能请求没有任何进展(?)。
@CharliePoole我在研究代码时遇到的潜在问题之一是现在如何处理 Fixtures。 当前,所有 WorkItem 都可以访问同一个 Fixture 实例,这意味着如果要并行执行 WorkItem,它们将访问测试类的单个实例。 这是有问题的,因为当测试依赖 Setup 或 Teardown 来设置实例级别字段时,它会创建竞争条件。
对此的一种解决方案是让每个 WorkItem 对测试类的一个新实例进行操作,但这可能会使 Fixture 设置的行为方式变得复杂,因为将不再有该 Fixture 的单个实例
@chris-smith-zocdoc 是的,这是 NUnit 与其前身 junit 之间的最大区别。 回到当天,它被广泛讨论了正反面,但现在没有太多提及。 出于这个原因,NUnit 测试应该是无状态的,所有的初始化都在 SetUp 方法中执行。
一旦引入了 TestFixtureSetUp(现在称为 OneTimeSetUp),就可以进行一次更昂贵的初始化并让所有测试都对相同的初始化值进行操作。 这在创建被测试类的实例时最有用,这些实例本身可能是有状态的。 近年来,越来越多的用户开始使用这种功能。
添加选项以创建每个测试用例的单独用户夹具实例的主题会定期出现。 到目前为止,它还没有达到计划功能的阶段。 这肯定与用户方面并行方法功能的可用性有关,但我认为它与实现是正交的。 如果我们为每个实例创建一个新装置,我们将简单地多次运行“一次”设置。 当然,这会对任何使用静力学的用户造成沉重打击。 😢
我们推迟并行测试方法有两个原因:(1) 难以实现;(2) 似乎并行装置虽然对我们来说更容易,但对大多数用户来说已经足够了。 似乎很少有用户跨多个设备共享状态,而看起来(基于在线讨论)许多用户跨测试方法共享状态。 到目前为止,很多用户都在利用并行性,虽然有些用户非常想要方法并行性,但他们似乎是一个相对较小的群体。
尽管如此,我想是时候做点什么了。 我将在第一季度进行这项工作,至少要进行一些实验,并可能提出其他人可以跟进的合理任务细分。
如果我们为每个实例创建一个新装置,我们将简单地多次运行“一次”设置。 当然,这会对任何使用静力学的用户造成沉重打击。
我认为,如果您选择并行运行,则要求没有静态状态是合理的,在某种程度上,如果某些东西因混合静态和并行性而中断,那是您的错。 幸运的是,您的所有代码都将接受测试,所以应该很难错过😆
尽管如此,我想是时候做点什么了。 我将在第一季度进行这项工作,至少要进行一些实验,并可能提出其他人可以跟进的合理任务细分。
算我一个。
我也是!
2017 年 1 月 14 日星期六上午 3:58,Joseph Musser通知@ github.com
写道:
>
>
>
>
[图片:Boxbe] https://www.boxbe.com/overview
自动清理:保留最后 1 封电子邮件 ([email protected])
如果我们为每个实例创建一个新装置,我们只需运行“one”
时间设置不止一次。 当然,这会严重打击任何用户
利用静力学。我认为要求没有静态状态是合理的,如果你
选择并行运行,如果有什么事情是你的错
中断混合静态和并行性。 幸运的是,所有这些代码都会
正在测试中,所以应该很难错过:D尽管如此,我想是时候做点什么了。 我要接受这个
对于第一季度,至少在进行一些实验的程度上
并可能提出其他人可以的合理分解任务
跟进。算我一个。
—
您收到此消息是因为您发表了评论。
直接回复本邮件,在GitHub上查看
https://github.com/nunit/nunit/issues/164#issuecomment-272488655或静音
线程
https://github.com/notifications/unsubscribe-auth/AAHNVlwVps8pQ93UIwZw6zY7TOyHO0a6ks5rR61EgaJpZM4CUZ8r
.
运行一些计时测试,我发现了一些有趣的事情。 调用可并行测试用例存在歧义。 这也可能适用于固定装置和其他套件,但不太明显。
事情是这样的:如果一个方法是完全不可并行的,那意味着它不能与__任何其他方法__并行运行。 OTOH,如果它只是在它的夹具内不可并行,那么它不能与同一夹具中的__任何其他方法并行运行。__
我建议我们按如下方式处理这种区别:
如果测试方法没有 Parallelizable 属性,则它应该在与其包含的夹具相同的线程上运行,前提是没有其他属性(例如 Apartment)要求它在不同的线程上运行
如果它具有范围为 Self 的 Parallelizable 属性,或者如果更高级别的套件指定了 Children 的范围,则测试方法将与夹具中的其他方法并行运行。
@nunit/core-team 的想法?
上面遗漏了:
@CharliePoole - 您的三点是有道理的,尽管我不清楚您建议我们不这样做的替代方案是什么。 你能澄清一下吗?
我们目前将没有属性与具有 ParallelScope.None 的属性相同。 如果我启用分派它们并且测试运行显着减慢,这会使它们在非并行队列中排队。
PR #2011 为实现此功能采取了一些初始步骤,但包含一个 #define,强制测试用例在其包含的夹具的线程上运行。 此评论记录了我认为需要做的事情才能消除该限制。
目前,fixture 的 OneTimeTearDown 在用于完成最后一个测试用例执行的线程上运行。 如果测试用例并行运行,我们无法预测将是哪个测试用例。 它可能是与固定装置所需特征不同的螺纹。 例如,如果要完成的最后一个测试是在 STA 中运行,那么即使 OneTimeSetUp 在 MTA 中运行,也将使用它来运行 OneTimeTearDown。 在许多情况下,这可能不会引起任何问题,但在某些情况下可能会引起任何问题。
这实际上也可能是更高级别的装置的问题,但是并行测试用例的引入意味着将有更多的不匹配机会导致错误。
因此,为了确保夹具拆卸发生在正确类型的线程上,我们不能再在要执行的最后一个测试的线程上运行它。 取而代之的是,调度程序需要维护有关所有挂起拆卸的信息,并被通知在适当的时间在适当的线程上运行这些拆卸。 弄清楚如何做到这一点是此功能的“设计”阶段。
对于从一开始(早在 2014 年)就一直关注此线程并且在等待此功能添加时不想或无法实现自己的解决方法的任何人,我刚刚偶然发现了使用 NUnit 2.6.3 的实现CodePlex 看起来非常易于使用(我已经验证它可以在多个并行线程中运行我们的功能测试)。
如果此消息与最近关于此线程的讨论有点正交,请提前向@CharliePoole道歉,但如果其他人在过去 3 年里一直在等待基于 NUnit 3 的承诺添加此功能(早在早期天),我认为它可能会提供一个解决方案,直到你们设法解决设计问题(听起来你正在接近解决方案)。
@查理普尔
因此,为了确保夹具拆卸发生在正确类型的线程上,我们不能再在要执行的最后一个测试的线程上运行它。 取而代之的是,调度程序需要维护有关所有挂起拆卸的信息,并被通知在适当的时间在适当的线程上运行这些拆卸。 弄清楚如何做到这一点是此功能的“设计”阶段。
我们是否需要调度员预先知道待处理的拆卸项目,或者我们可以在它们可用时调度它们? 更具体地说,在 CompositeWorkItem 当前调用PerformOneTimeTearDown 的地方,我们
@chris-smith-zocdoc 是的,这正是我正在做的。 我创建了一种新类型的工作项OneTimeTearDownWorkItem
,它嵌套在CompositeWorkItem
并在运行最后一个子测试时分派。 稍后,当 OneTimeSetUp 和所有测试都在同一线程上运行时,我们可能会查看一些效率。
还没有仔细阅读所有内容,但作为此功能的一部分,我想要求的一件事是并行性是“智能的”,尤其是对于 I/O 绑定测试。 例如,如果您有 10 个线程执行 100 个可并行测试,那么这 10 个线程不应该坐等前 10 个测试完成,然后再进行接下来的 10 个测试。 如果前 10 个测试开始等待非常长时间运行的 I/O 任务,那么线程应该可以自由地转移到其他测试。 当 I/O 任务完成时,线程将在线程空闲时继续等待测试。
基本上,我要求对广泛使用 async/await 的 I/O 绑定测试进行智能吞吐量管理。 到目前为止,这是我们在测试中的第一大瓶颈。
@chris-smith-zocdoc 事实上,这就是我正在做的事情。 我基本上是在使用现有的倒计时机制来触发一次性拆卸任务的调度。 诀窍是让它在适当的队列上分派。
@gzak请记住,并行执行机制已经存在。 它依赖于工人独立地拉动任务,而不是有一个控制器将任务推送给工人。 因此,如果一个 worker 忙于某个任务一段时间,其他 worker 将继续独立执行其他任务。 诀窍是根据正在运行的测试的性质设置工作人员的数量。 默认情况下,NUnit 在正常的、受计算约束的单元测试中表现得相当好,但其他类型的测试可能需要用户设置适当的并行级别。
有人可以解释一下它是如何工作的吗?
我有一个测试班
当我在这个类中非并行运行测试时 - 所有测试都通过了
但是当我用 [Parallelizable(ParallelScope.Children)] 运行它们时
所以它们确实并行运行(同一类中的多个方法)
但由于某种原因,一些测试失败了。
我在这个类中有跨测试使用的实例字段,似乎这些字段在线程之间共享
我对吗?
您是否只创建了该类的 1 个实例并在该单个对象上同时调用这些方法?
查理普尔
你想通了! 是的,夹具中的所有测试都使用相同的实例。 这是 NUnit 的历史,它一直以这种方式工作。 您必须在并行运行测试用例和根据测试修改任何状态之间做出选择。 目前没有办法解决。
也就是说,如果你有相当比例的灯具,简单地并行运行灯具可以给你良好的性能。
是否有可能在 [Parallelizable(ParallelScope.Children)] 中
AssemblyInfo.cs 文件?
有没有人看到这工作?
2017 年 6 月 14 日 01:37,查理普尔通知@github.com 写道:
[图片:Boxbe] https://www.boxbe.com/overview自动清理:保持
最后 1 封电子邮件 ([email protected]) 编辑规则
https://www.boxbe.com/popup?url=https%3A%2F%2Fwww.boxbe.com%2Fcleanup%3Fkey%3DCCP9ir0TebdbdQOWVtGMQyr2TETYOrzfkbItPzUTgDk%253D%26token%3D0PvYtf1G2B%252FJ2FNN3b7MTSmP1zvs6x3Cu8z6LaAB8%252BJm73uy8ZNUCnQcknlgWKxRQ5zjE%252BY30Xkv1W1Gue9gGnpyi72YUTaHP2h6wvuEpTXe1WoQDoSHpUGDQefgQu6LDH0rRhsEvF%252FW%252BhysbMtsDw%253D% 253D&tc_serial=30872123699&tc_rand=2087335475&utm_source=stf&utm_medium=email&utm_campaign=ANNO_CLEANUP_EDIT&utm_content=001
| 删除规则
https://www.boxbe.com/popup?url=https%3A%2F%2Fwww.boxbe.com%2Fcleanup%3Fkey%3DCCP9ir0TebdbdQOWVtGMQyr2TETYOrzfkbItPzUTgDk%253D%26token%3D0PvYtf1G2B%252FJ2FNN3b7MTSmP1zvs6x3Cu8z6LaAB8%252BJm73uy8ZNUCnQcknlgWKxRQ5zjE%252BY30Xkv1W1Gue9gGnpyi72YUTaHP2h6wvuEpTXe1WoQDoSHpUGDQefgQu6LDH0rRhsEvF%252FW%252BhysbMtsDw%253D% 253D&tc_serial=30872123699&tc_rand=2087335475&utm_source=stf&utm_medium=email&utm_campaign=ANNO_CLEANUP_EDIT&utm_content=001
| 标记重要
https://www.boxbe.com/popup?url=https%3A%2F%2Fwww.boxbe.com%2Fcleanup%3Fkey%3DCCP9ir0TebdbdQOWVtGMQyr2TETYOrzfkbItPzUTgDk%253D%26token%3D0PvYtf1G2B%252FJ2FNN3b7MTSmP1zvs6x3Cu8z6LaAB8%252BJm73uy8ZNUCnQcknlgWKxRQ5zjE%252BY30Xkv1W1Gue9gGnpyi72YUTaHP2h6wvuEpTXe1WoQDoSHpUGDQefgQu6LDH0rRhsEvF%252FW%252BhysbMtsDw%253D% 253D%26important%3Dtrue%26emlId%3D61187554820&tc_serial=30872123699&tc_rand=2087335475&utm_source=stf&utm_medium=email&utm_campaign=UP_ENO_CUT0你想通了! 是的,夹具中的所有测试都使用相同的实例。
这是 NUnit 的历史,它一直以这种方式工作。 你必须
在并行运行测试用例和具有任何状态之间进行选择
根据测试修改。 目前没有办法解决。也就是说,如果你有相当比例的固定装置,只需运行
并联灯具可以为您提供良好的性能。—
您收到此消息是因为您发表了评论。
直接回复本邮件,在GitHub上查看
https://github.com/nunit/nunit/issues/164#issuecomment-308157832或静音
线程
https://github.com/notifications/unsubscribe-auth/AAHNVuK-J-X74mlAA_eT7OX7dxs7MpoRks5sDqzLgaJpZM4CUZ8r
.
@agray是的,事实上这是我现在拥有 AssemblyInfo.cs 的唯一原因。
嗨约瑟夫,
您要在 AssemblyInfo.cs 文件中添加什么并行度线?
我很想知道什么有效。
干杯,
安德鲁
2017 年 6 月 14 日星期三下午 4:17,Joseph Musser通知@ github.com
写道:
[图片:Boxbe] https://www.boxbe.com/overview自动清理:保持
最后 1 封电子邮件 ([email protected]) 编辑规则
https://www.boxbe.com/popup?url=https%3A%2F%2Fwww.boxbe.com%2Fcleanup%3Fkey%3DnRGYOf%252FKR68McP8RTipuFTLF9WUvAkSKSh6OYJYvJ2w%253D%26token%3DDcwWzMT9yPtQLckdXD3BLhW5xAB%252BMpc9XdsrbBlwdQJZC%252Bjo3SjsyMVC8vese%252BCNRw2IyucWqEcHR5Is7CK7nx01VuSQESvjG4ZUj%252B2Cfcwg51yUFFQJSwrmTVxqAk4%252BTVGDSrnutdAuqiJ3kTaYQA% 253D%253D&tc_serial=30882364582&tc_rand=1974513896&utm_source=stf&utm_medium=email&utm_campaign=ANNO_CLEANUP_EDIT&utm_content=001
| 删除规则
https://www.boxbe.com/popup?url=https%3A%2F%2Fwww.boxbe.com%2Fcleanup%3Fkey%3DnRGYOf%252FKR68McP8RTipuFTLF9WUvAkSKSh6OYJYvJ2w%253D%26token%3DDcwWzMT9yPtQLckdXD3BLhW5xAB%252BMpc9XdsrbBlwdQJZC%252Bjo3SjsyMVC8vese%252BCNRw2IyucWqEcHR5Is7CK7nx01VuSQESvjG4ZUj%252B2Cfcwg51yUFFQJSwrmTVxqAk4%252BTVGDSrnutdAuqiJ3kTaYQA% 253D%253D&tc_serial=30882364582&tc_rand=1974513896&utm_source=stf&utm_medium=email&utm_campaign=ANNO_CLEANUP_EDIT&utm_content=001
| 标记重要
https://www.boxbe.com/popup?url=https%3A%2F%2Fwww.boxbe.com%2Fcleanup%3Fkey%3DnRGYOf%252FKR68McP8RTipuFTLF9WUvAkSKSh6OYJYvJ2w%253D%26token%3DDcwWzMT9yPtQLckdXD3BLhW5xAB%252BMpc9XdsrbBlwdQJZC%252Bjo3SjsyMVC8vese%252BCNRw2IyucWqEcHR5Is7CK7nx01VuSQESvjG4ZUj%252B2Cfcwg51yUFFQJSwrmTVxqAk4%252BTVGDSrnutdAuqiJ3kTaYQA% 253D%253D%26important%3Dtrue%26emlId%3D61214070592&tc_serial=30882364582&tc_rand=1974513896&utm_source=stf&utm_medium=email&utm_itm_campaign0@array https://github.com/array是的,事实上这是我唯一的原因
现在有一个 AssemblyInfo.cs。—
您收到此消息是因为您发表了评论。
直接回复本邮件,在GitHub上查看
https://github.com/nunit/nunit/issues/164#issuecomment-308325726或静音
线程
https://github.com/notifications/unsubscribe-auth/AAHNVghNAX8CJkqAy-qhAz8bXNhZcFOQks5sD3NigaJpZM4CUZ8r
.
@aray你问的那个:
c#
[Parallelizable(ParallelScope.Children)]
不要忘记目标
[assembly: Parallelizable(ParallelScope.Children)]
@LirazShay我使用 NUnit 来驱动 Selenium 测试,并且使用夹具级别的字段来保存对用户帐户和我正在使用的 Selenium WebDriver 实例的引用等内容,因此无法在夹具中并行运行测试。 我解决这个问题的方法是编写一个实现 IDisposable 的“工厂”(我使用引号,因为我不确定它是正确的术语),它为每个测试封装了我所有的测试需求,并在结束时干净地将它们拆除测试不需要 [TearDown] 或 [OneTimeTearDown] 有点像这样:
public class TestFactory : IDisposable
{
// Instantiate a new SafeHandle instance.
private readonly System.Runtime.InteropServices.SafeHandle handle = new Microsoft.Win32.SafeHandles.SafeFileHandle(IntPtr.Zero, true);
// Flag: Has Disposed been called?
private bool disposed = false;
public TestFactory()
{
this.UserRepository = new List<UserAccount>();
this.DU = new DataUtility();
}
// A list of users created for this test
public List<UserAccount> UserRepository { get; private set; }
// A very simple data layer utility that uses Dapper to interact with the database in my application
public DataUtility DU { get; private set; }
// Gets a new user and adds it to the repository
public UserAccount GetNewUser()
{
var ua = new UserAccount();
this.UserRepository.Add(ua);
return ua;
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (this.disposed)
{
return;
}
if (disposing)
{
// Deletes all user accounts created during the test
foreach (UserAccount ua in this.UserRepository)
{
try
{
ua.Delete();
}
catch (Exception)
{
// Take no action if delete fails.
}
}
this.DU.DeleteNullLoginFailures(); // Cleans up the database after tests
Thread.Sleep(1500);
}
this.disposed = true;
}
}
然后,在测试中我可以这样做:
[TestFixture]
public class UserConfigureTests
{
[Test]
public void MyExampleTest()
{
using (TestFactory tf = new TestFactory())
{
var testUser = tf.GetNewUser();
tf.DU.DoSomethingInTheDatabase(myParameter);
// Test actions go here, and when we exit this using block the TestFactory cleans
// up after itself using the Dispose method which calls whatever cleanup logic you've written into it
}
}
}
这样,我可以避免大量代码重复,而且如果我需要更改测试的依赖项,我只需在工厂中执行一次即可。 如果有人对我采取的策略有反馈意见,我将不胜感激!
@tparikka我自己强烈推荐这种方法。
我的 AssemblyInfo 文件中有以下内容:
[组装:Parallelizable(ParallelScope.Children)]
[组装:LevelOfParallelism(16)]
我还需要 LevelOfParallelism 属性吗?
2017 年 6 月 15 日 04:37,Joseph Musser [email protected]写道:
[图片:Boxbe] https://www.boxbe.com/overview自动清理:保持
最后 1 封电子邮件 ([email protected]) 编辑规则
https://www.boxbe.com/popup?url=https%3A%2F%2Fwww.boxbe.com%2Fcleanup%3Fkey%3Doth%252FFbAPG%252FhDbtUlS0i2PDDdQ0lP4dBi8o7QQmkLEMQ%253D%26token%3DHe7HfTrm%252Fiba3yIDazaBx8JO9NrmoL8p5TWtDB1hUxq0qp%252BhCRCB3OSl7sUQ6wDshc2I5LQhbR2jszLWr6FnRy%252FZUrCqghZIIilbDWKszT7pkI44xp9vaL6cszH9Sgg1YPCAHdVWqccZYxYXGW174A%253D% 253D&tc_serial=30894750852&tc_rand=1847060911&utm_source=stf&utm_medium=email&utm_campaign=ANNO_CLEANUP_EDIT&utm_content=001
| 删除规则
https://www.boxbe.com/popup?url=https%3A%2F%2Fwww.boxbe.com%2Fcleanup%3Fkey%3Doth%252FFbAPG%252FhDbtUlS0i2PDDdQ0lP4dBi8o7QQmkLEMQ%253D%26token%3DHe7HfTrm%252Fiba3yIDazaBx8JO9NrmoL8p5TWtDB1hUxq0qp%252BhCRCB3OSl7sUQ6wDshc2I5LQhbR2jszLWr6FnRy%252FZUrCqghZIIilbDWKszT7pkI44xp9vaL6cszH9Sgg1YPCAHdVWqccZYxYXGW174A%253D% 253D&tc_serial=30894750852&tc_rand=1847060911&utm_source=stf&utm_medium=email&utm_campaign=ANNO_CLEANUP_EDIT&utm_content=001
| 标记重要
https://www.boxbe.com/popup?url=https%3A%2F%2Fwww.boxbe.com%2Fcleanup%3Fkey%3Doth%252FFbAPG%252FhDbtUlS0i2PDDdQ0lP4dBi8o7QQmkLEMQ%253D%26token%3DHe7HfTrm%252Fiba3yIDazaBx8JO9NrmoL8p5TWtDB1hUxq0qp%252BhCRCB3OSl7sUQ6wDshc2I5LQhbR2jszLWr6FnRy%252FZUrCqghZIIilbDWKszT7pkI44xp9vaL6cszH9Sgg1YPCAHdVWqccZYxYXGW174A%253D% 253D%26important%3Dtrue%26emlId%3D61245244440&tc_serial=30894750852&tc_rand=1847060911&utm_source=stf&utm_medium=email&utm_campaign=UP_ENO_CUT0@tparikka https://github.com/tparikka我强烈推荐那个
接近我自己。—
你收到这个是因为你被提到了。
直接回复本邮件,在GitHub上查看
https://github.com/nunit/nunit/issues/164#issuecomment-308521058或静音
线程
https://github.com/notifications/unsubscribe-auth/AAHNVmEzVDbw32Xx0jkYcGK9bZW3tLvXks5sECh8gaJpZM4CUZ8r
.
我还没有考虑使用LevelOfParallelism
。 它默认为您拥有的核心数。
如果您的测试不受 CPU 限制,则更高是有意义的。 但是与 perf 一样,答案非常依赖于您的场景,因此最好进行测量而不是猜测。
@CharliePoole我正在使用TestcaseSource
,但看起来生成的测试用例实际上并未并行执行。 像这样的东西是否会起作用:
```c#
[测试装置]
类反序列化
{
公共静态 IEnumerable
[TestCaseSource("ShouldDeserializeAllCases"), Parallelizable(ParallelScope.Children)]
public void ShouldDeserializeAll(TimeSpan t)
{
Thread.Sleep(t);
Assert.AreEqual(1, 1);
}
}
``
所用的总时间是 10 秒而不是 2 秒。
我会认为没有孩子,所以在这种情况下,你可以更好地使用
[可并行化(ParallelScope.All)]
或在班级级别移动您的属性。
@ParanoikCZE谢谢。 我实际上对该属性的含义一无所知,所以我已经尝试了那里的所有枚举值。 无论我使用All
、 Children
、 Fixture
还是Self
的哪一个,我都会得到 10 秒的执行时间(至少在 Visual Studio 中)。
我只是尝试将它移到课堂上,但这似乎也无济于事。
试试这是灵感的来源:)
class Deserialization
{
public static IEnumerable<TestCaseData> ShouldDeserializeAllCases
{
get
{
for (int i = 1; i <= 5; i++)
yield return new TestCaseData(TimeSpan.FromSeconds(i)).SetName($"Thread_worker_{i}");
}
}
[TestCaseSource(nameof(ShouldDeserializeAllCases)), Parallelizable(ParallelScope.Children)]
public void ShouldDeserializeAll(TimeSpan t) => System.Threading.Thread.Sleep(t);
}
@ParanoikCZE再次感谢。 我在 Visual Studio 中对此进行了测试,可视化效果更加清晰,但测试仍在按顺序运行。 如果您对每个测试用例使用持续睡眠而不是增加步骤,则更容易看到这一点。
尝试将 [assembly: LevelOfParallelism(5)] 添加到 AssemblyInfo 中,我认为有一些默认值,但也许它以某种方式对您不起作用。 无论如何,我没有想法。 :)
最有用的评论
虽然我可以假装预测未来,但那只会让你满意到九月。 :-)
让我通过解释我们如何“安排”功能来回答。
我们目前正在尝试(从年初开始)一种每季度发布一次的方法。 随着我们在发布方面做得更好,我们可能会加快步伐。 最终,我们或许能够进行持续部署。
在志愿开源项目中,每个月没有固定的可用工作量。 我们可以使用“昨天的天气”方法,但事实证明,人们必须在 NUnit 上花费的时间以及志愿服务的人数变化很大。
作为妥协,我们选择了少量对发布至关重要的问题,并提前将它们添加到里程碑中。 我的偏好是添加不超过我们希望完成的大约 25%。 发布中的大多数问题仅在完成后或充其量有人承诺处理它们时才会添加到该里程碑。 如果没有人指派给他们,你通常不会在我们的 3.5 里程碑中找到未解决的问题,尽管我偶尔会这样做,如果它看起来像阻碍了其他工作。
因此,我们所做的积极的一面是我们几乎可以保证发布会按时发布。 不利的一面是我们无法告诉您其中会包含什么。 :-(
对于这个特定的问题...我已将其置于高度优先级以告诉我们的开发人员它很重要。 必须有人可以自由地工作,并且有足够的背景来完成这种范围和难度的项目。 如果有合适背景的人在接下来的几周内接受了这一点,我想这可以通过发布来完成。 作为指导方针,我认为我需要大约一个月的时间,同时还要处理其他一些事情,才能通过我的方式解决这个问题。
抱歉,没有更明确的答案,但这样的答案必然是谎言!