简体   繁体   English

Jenkins失败单位CanExecute测试的方法不确定

[英]Jenkins failed unit CanExecute test's methods nondeterministic

We have a lot CanExecute tests for a various commands in our project. 我们在项目中对各种命令进行了很多CanExecute测试。 All tests passed properly when we use Visual Studio testing or AxoCover. 当我们使用Visual Studio测试或AxoCover时,所有测试都正确通过。

We tried to add some previous object initialization, before executing 'CanExecute' and sometimes it worked (or we thought that). 我们尝试在执行'CanExecute'之前添加一些先前的对象初始化,有时它可以工作(或者我们认为)。

testedViewModel.Object.InEditMode = inEditMode;

I have a test: 我有一个测试:

[TestCase(true, true, TestName = "Command_InEditMode_CanExecute")]
[TestCase(false, false, TestName = "Command_NotInEditMode_CannotExecute")]
public void CommandCanExecute(bool inEditMode, bool expectedResult)
{
    var testedViewModel =
        new Mock<SomeViewModel>(inEditMode)
        {
            CallBase = true
        };

    testedViewModel.Setup(x => x.InEditMode).Returns(inEditMode);

    Assert.AreEqual(expectedResult, testedViewModel.Object.Command.CanExecute(null));
}

Sometimes (NOT ALWAYS) when Jenkins does the build and run unit tests some of can execute tests failed with message: 有时(不是总是)当Jenkins进行构建并运行单元测试时,一些可以执行测试失败的消息:

MESSAGE:
  Expected: True
  But was:  False

+++++++++++++++++++  
STACK TRACE:
   at Project.CommandCanExecute(Boolean inEditMode, Boolean expectedResult)

The problem is that is happening only on Jenkins and it's very nondeterministic. 问题是只在Jenkins上发生,这是非常不确定的。

EDIT: 编辑:

Ok, one more thing to think about. 好的,还有一件事要考虑。 Property InEditMode is placed in base parent class of SomeModelView. 属性InEditMode位于SomeModelView的基本父类中。

And I merged code for you in the sample. 我在示例中为您合并了代码。

public BaseViewModel 
{
    public virtual bool InEditMode {get; set;}
}

public SomeViewModel : BaseViewModel
{
    public SomeViewModel () : base ()
    {

    }

    public ICommand Command { get; set; }

    public virtual void RegisterCommands()
    {
        Command = new RelayCommand(/*Do something*/, () => InEditMode);
    }
}

And we think that can be related, that object is thinking that is initialized before initialization of base class is done. 我们认为这可能是相关的,该对象认为在基类初始化完成之前已初始化。 But that is very hard to check this with a Jenkins. 但是用Jenkins来检查这个很难。


SOLUTION

I've created an attribute class: 我创建了一个属性类:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Assembly, AllowMultiple = true)]
public class GarbageCollectorDisabler : Attribute, ITestAction
{
    public void BeforeTest(ITest test)
    {
        GC.TryStartNoGCRegion(2048 * 4096);
    }

    public void AfterTest(ITest test)
    {
        GC.EndNoGCRegion();
    }

    public ActionTargets Targets => ActionTargets.Test;
}

And then I can use for each 'CanExecute' test this attribute: 然后我可以使用每个'CanExecute'测试这个属性:

[GarbageCollectorDisabler]
[TestCase(TestName = "SomeTest_InEditMode_CanExecute")]
public void SomeTestCanExecute()
{}

Smells like a garbage collection issue to me. 闻起来像垃圾收集问题给我。 I don't see anything that jumps out at me in your sample, though the code sample is incomplete (where is RegisterCommands invoked?) so something crucial could be missing. 虽然代码示例不完整( RegisterCommands在哪里被调用?),但我没有看到你的样本中有任何东西突然出现,所以可能缺少一些关键的东西。

See the source for RelayCommand.CanExecute() . 请参阅RelayCommand.CanExecute()的源代码。 It takes a weak reference to the action you pass in, and once that action is collected CanExecute will return false . 它会对您传入的操作进行弱引用,一旦收集到该操作, CanExecute将返回false See my answer here for an example of this happening. 请参阅我的答案了解这种情况的一个例子。

I reiterate @Nkosi's comment, create a minimal example rather than showing us bits and pieces. 我重申@Nkosi的评论,创造一个最小的例子而不是向我们展示点点滴滴。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM