How to stop MsTest tests execution after *n* failed tests - unit-testing

I want to run unit tests via MS Test (from windows console) in a way that I can stop/kill the test execution whenever the failed tests count exceeds certain threshold value.
For my use case there is no point to keep running tests when certain percentage of the tests already failed.
I can only think in creating a new console app to wrap the mstest.exe execution, so I can parse the standard output in real-time,
and eventually kill the process, for example:
var pi = new ProcessStartInfo()
{
FileName = MS_TEST,
UseShellExecute = false,
RedirectStandardOutput = true,
Arguments = MS_TEST_ARGS
};
int passed = 0; int failed = 0;
using (var process = Process.Start(pi))
{
while (!process.StandardOutput.EndOfStream)
{
string line = process.StandardOutput.ReadLine();
if (line.Contains("Passed"))
passed++;
if (line.Contains("Failed"))
failed++;
if (failed >= THRESHOLD)
{
process.Kill();
break;
}
}
}
Can anyone suggest a better way for doing this? I don't think this is natively supported by MsTest.
PowerShell seems to be an option, but the stdout redirect is not trivial.
Update
As a note, I cannot modify the test code, I need this to be done without modifying the tests code in any way.

Create a BaseTestClass which contains a method responsible for killing the process that runs the tests.
using System.Diagnostics;
namespace UnitTestProject1
{
public class BaseTestClass
{
private readonly int _threshold = 1;
private static int _failedTests;
protected void IncrementFailedTests()
{
if (++_failedTests >= _threshold)
Process.GetCurrentProcess().Kill();
}
}
}
Your must inherit all your test classes from BaseTestClass and use the [TestCleanup] attribute. The TestCleanup() method is evaluated when a test defined in the DemoTests class has finished running. Is in that method where we evaluate the output of the test that has just finished. If it failed, we kill the process responsible for running the tests.
In the following example we have defined three tests. The second test, Test_Substracting_Operation(), is intended to fail intentionally, so the third test will never be run.
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnitTestProject1
{
[TestClass]
public class DemoTests : BaseTestClass
{
public TestContext TestContext { get; set; }
[TestCleanup]
public void TestCleanup()
{
if (TestContext.CurrentTestOutcome == UnitTestOutcome.Failed)
{
IncrementFailedTests();
}
}
[TestMethod]
public void Test_Adding_Operation()
{
// Arrange
int x = 1;
int y = 2;
// Act
int result = x + y;
// Assert
Assert.AreEqual(3, result);
}
[TestMethod]
public void Test_Substracting_Operation()
{
// Arrange
int x = 1;
int y = 2;
// Act
int result = x - y;
// Assert
Assert.AreEqual(100, result);
}
[TestMethod]
public void Test_Multiplication_Operation()
{
// Arrange
int x = 1;
int y = 2;
// Act
int result = x * y;
// Assert
Assert.AreEqual(2, result);
}
}
}

Related

Unit Test - call a function in two test cases if the function is called only once in productive code

maybe there is someone who has experience with Unit Testing with cpputest.
I have something like this:
Source code Under Test:
main_function()
{
static int8 is_functioncalled = 1;
if (is_functioncalled){
my_local_function();
is_functioncalled = 0
}
UNIT Test Environment:
TEST(TESTGROUP,TEST_CASE1){
//Some Unit Test checks of my_local_function()
main_function();
}
TEST(TESTGROUP,TEST_CASE2){
//Some other Unit Test stuff
main_function(); // --> my_local_function() will not be called in this test case because it's called already before
}
I need in TEST_CASE2 the function my_local_function() to be called again. This function is indirectly called through the public interface main_function() which can be called directly within the Unit Test. Does anybody have an idea how to do this in generally or in cpputest environment ?
Try to override setup() method of test group - it will be called before each test. You could reset is_functioncalled flag there if you would put it in global scope, something like this:
static int8 is_functioncalled = 1;
main_function()
{
if (is_functioncalled){
my_local_function();
is_functioncalled = 0
}
}
//
extern int8 is_functioncalled; // If its in global scope in other source file
TEST_GROUP(TESTGROUP)
{
void setup()
{
is_functioncalled = 1;
}
}
Try https://cpputest.github.io/manual.html - there's all you need to know.
You may add a define into your code, modifying behaviour if it is under testing:
main_function()
{
static int8 is_functioncalled = 1;
#ifdef UNITTEST
is_functioncalled = 1;
#endif
if (is_functioncalled){
my_local_function();
is_functioncalled = 0
}

Unit test just returns 1 result of 10 cases from loop

i am trying to get all 10 results of 10 cases from For loop. but when i run, it just returns for me the first result of the first time. any help for this condition, this is my whole code, it includes
2 files, i have tried many times to fix it.
//file BankAccount.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Bank //just want to demo this thing, it hasn't completed
{
namespace BankAccountNS
{
public class BankAccount
{
private double m_balance;
public BankAccount(double balance)
{
m_balance = balance;
}
public bool getMoney(double amount) //funtion get money from account
{
if (amount > m_balance || amount < 0) //check money
{
return false;
}
return true;
}
}
}
}
//file BankAccountTests.cs
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Bank.BankAccountNS;
namespace BankTest
{
[TestClass]
public class BankAccountTests
{
[TestMethod]
public void TestEveryDebit(BankAccount Ba) //test every case from TestAll
{
Assert.IsTrue(Ba.getMoney(24000));
}
[TestMethod]
public void TestAll() //create all cases
{
for(int i = 0; i < 10; i++)
{
BankAccount Ba = new BankAccount(23996 + i);
TestEveryDebit(Ba);
}
}
}
}
I'm not really clear on what your (attempted) loop asserts would be accomplishing, but the method getMoney seemingly has 2 (or 3) useful unit tests:
Is the amount greater than the balance I have? - return false
Is my account balance less than zero - return false
Is my amount less than or equal too my balance? - return true
In your current setup (if it were to work) you're simply testing getMoney is returning true for amounts even greater than the balance - this is incorrect and does not adhere to the logic you have coded too.
I see your unit tests looking like:
private double _balance = 50;
private BankAccount _unitTestObject;
[TestMethod]
public void getMoney_returnsFalseWithInsufficientFunts() //create all cases
{
_unitTestObject = new BankAccount(_balance );
var results = _unitTestObject.getMoney(_balance+1);
Assert.IsFalse(results);
}
[TestMethod]
public void getMoney_returnsFalseWhenAccountHasLessThanZero() //create all cases
{
_unitTestObject = new BankAccount(-1);
var results = _unitTestObject.getMoney(1);
Assert.IsFalse(results);
}
[TestMethod]
public void getMoney_returnsTrueWhenAccountSufficientBalance() //create all cases
{
_unitTestObject = new BankAccount(_balance);
var results = _unitTestObject.getMoney(_balance);
Assert.IsTrue(results);
}
As I stated in comments, MSTest can't do parameterized tests, and what it looks like you're attempting to do (assert specific logic 10 times) could be done like this:
[TestClass]
public class BankAccountTests
{
[TestMethod]
public void TestAll() //create all cases
{
for(int i = 0; i < 10; i++)
{
BankAccount Ba = new BankAccount(23996 + i);
TestEveryDebit(Ba);
}
}
private void TestEveryDebit(BankAccount Ba) //test every case from TestAll
{
Assert.IsTrue(Ba.getMoney(24000));
}
}
But the test TestAll will always fail, because at some point in your loop, you're going to be trying to take out more amount than you have balance.
When Asserting based on a loop, the "success or failure" of the test is based on the whole, not each individual assert. So even though a few runs of your loop will "pass", the test will fail as a whole.

How to break dependency on StreamReader's readLine() method in microsoft fakes unit testing?

Here is my code in one of the method which I want to test:
using (var sr = new StreamReader(myFile))
{
string line;
while ((line = sr.ReadLine()) != null)
{
if (line.Equals("completed"))
{
continue; //here it is getting called infinite times
}
if(line.Equals("processed"))
{
break;
}
}
}
In my test method I have written below code with the help of shim:
ShimStreamReader.ConstructorString = delegate (StreamReader #this, string #string)
{
var reader = new ShimStreamReader(#this);
reader.ReadLine = () =>
{
return "completed";
};
};
Now I dont want to pass the file. Instead I want to pass the stream of characters or string.
Above test code is calling and breaking the dependency of new StreamReader(myFile) as expected and entering into while loop.
As soon as it is entering it in while loop, sr.ReadLine() is returning "completed" all the time. So I'm stuck here. How would I stop here or how would I write the input string so that as soon as my first call return completed in second call of sr.ReadLine() it should return null, and then breaks the loop?
You're more into a general coding question here rather than fakes. All you need to do is add a flag and set it when you're ready to end the input. This is the code I used
private bool _lineSent = false;
[TestMethod]
public void ReaderTest()
{
using (ShimsContext.Create())
{
ShimStreamReader.ConstructorString = (reader, s) =>
{
ShimStreamReader shimReader = new ShimStreamReader(reader);
shimReader.ReadLine = () =>
{
if (!_lineSent)
{
_lineSent = true;
return "completed";
}
else
{
return null;
}
};
};
ClassToTest testInstance = new ClassToTest();
testInstance.ReadStream();
}
}
By the way, depending on your level and what you are trying to learn, you might want to look into dependency injection and using stubs rather then shims. Shims are handy and nice, but for new development and code under your control, try to use stubs.

Java 8 streams vs iterator performance

I'm comparing 2 ways to filter lists, with and without using streams. It turns out that the method without using streams is faster for a list of 10,000 items. I'm interested in understanding why is it so. Can anyone explain the results please?
public static int countLongWordsWithoutUsingStreams(
final List<String> words, final int longWordMinLength) {
words.removeIf(word -> word.length() <= longWordMinLength);
return words.size();
}
public static int countLongWordsUsingStreams(final List<String> words, final int longWordMinLength) {
return (int) words.stream().filter(w -> w.length() > longWordMinLength).count();
}
Microbenchmark using JMH:
#Benchmark
#BenchmarkMode(Throughput)
#OutputTimeUnit(MILLISECONDS)
public void benchmarkCountLongWordsWithoutUsingStreams() {
countLongWordsWithoutUsingStreams(nCopies(10000, "IAmALongWord"), 3);
}
#Benchmark
#BenchmarkMode(Throughput)
#OutputTimeUnit(MILLISECONDS)
public void benchmarkCountLongWordsUsingStreams() {
countLongWordsUsingStreams(nCopies(10000, "IAmALongWord"), 3);
}
public static void main(String[] args) throws RunnerException {
final Options opts = new OptionsBuilder()
.include(PracticeQuestionsCh8Benchmark.class.getSimpleName())
.warmupIterations(5).measurementIterations(5).forks(1).build();
new Runner(opts).run();
}
java -jar target/benchmarks.jar -wi 5 -i 5 -f 1
Benchmark Mode Cnt Score Error Units
PracticeQuestionsCh8Benchmark.benchmarkCountLongWordsUsingStreams thrpt 5 10.219 ± 0.408 ops/ms
PracticeQuestionsCh8Benchmark.benchmarkCountLongWordsWithoutUsingStreams thrpt 5 910.785 ± 21.215 ops/ms
Edit: (as someone deleted the update posted as an answer)
public class PracticeQuestionsCh8Benchmark {
private static final int NUM_WORDS = 10000;
private static final int LONG_WORD_MIN_LEN = 10;
private final List<String> words = makeUpWords();
public List<String> makeUpWords() {
List<String> words = new ArrayList<>();
final Random random = new Random();
for (int i = 0; i < NUM_WORDS; i++) {
if (random.nextBoolean()) {
/*
* Do this to avoid string interning. c.f.
* http://en.wikipedia.org/wiki/String_interning
*/
words.add(String.format("%" + LONG_WORD_MIN_LEN + "s", i));
} else {
words.add(String.valueOf(i));
}
}
return words;
}
#Benchmark
#BenchmarkMode(AverageTime)
#OutputTimeUnit(MILLISECONDS)
public int benchmarkCountLongWordsWithoutUsingStreams() {
return countLongWordsWithoutUsingStreams(words, LONG_WORD_MIN_LEN);
}
#Benchmark
#BenchmarkMode(AverageTime)
#OutputTimeUnit(MILLISECONDS)
public int benchmarkCountLongWordsUsingStreams() {
return countLongWordsUsingStreams(words, LONG_WORD_MIN_LEN);
}
}
public static int countLongWordsWithoutUsingStreams(
final List<String> words, final int longWordMinLength) {
final Predicate<String> p = s -> s.length() >= longWordMinLength;
int count = 0;
for (String aWord : words) {
if (p.test(aWord)) {
++count;
}
}
return count;
}
public static int countLongWordsUsingStreams(final List<String> words,
final int longWordMinLength) {
return (int) words.stream()
.filter(w -> w.length() >= longWordMinLength).count();
}
Whenever your benchmark says that some operation over 10000 elements takes 1ns (edit: 1µs), you probably found a case of clever JVM figuring out that your code doesn't actually do anything.
Collections.nCopies doesn't actually make a list of 10000 elements. It makes a sort of a fake list with 1 element and a count of how many times it's supposedly there. That list is also immutable, so your countLongWordsWithoutUsingStreams would throw an exception if there was something for removeIf to do.
You do not return any values from your benchmark methods, thus, JMH has no chance to escape the computed values and your benchmark suffers dead code elimination. You compute how long it takes to do nothing. See the JMH page for further guidance.
Saying this, streams can be slower in some cases: Java 8: performance of Streams vs Collections

constructor not getting called?

Ive been staring at my code and I can't figure out why on earth my constructor is not gettign called.
It's just ignoring my constructor completely (i've check with stepping with debugger).
Here's my testapp:
using namespace MyEngine;
int _tmain(int argc, _TCHAR* argv[])
{
TestManager* testMgr = new TestManager();
testMgr->RunAllTests();
delete testMgr;
getchar();
return 0;
}
TestManager.h:
namespace MyEngine
{
class TestManager
{
public:
TestManager();
TestManager(uint64_t RepeatTimes);
~TestManager();
bool RunAllTests();
bool RunMemoryTests();
private:
Engine* mEngine;
ILogManager* mLogger;
MemoryTestManager* mMemTestMgr;
uint64_t mRepeatTimes;
};
}
and TestManager.cpp
namespace MyEngine
{
TestManager::TestManager()
{
TestManager(1);
}
TestManager::TestManager(uint64_t RepeatTimes)
{
if (RepeatTimes>0)
mRepeatTimes = RepeatTimes;
else
{
mRepeatTimes = 1;
}
mEngine = Engine::GetEngine();
mMemTestMgr = new MemoryTestManager();
}
TestManager::~TestManager()
{
}
/* Runs all testing modules */
bool TestManager::RunAllTests()
{
bool res = true;
/* Init Engine */
if(mEngine->Init(0,0,0))
{
res = true;
res && mEngine->GetRenderManager()->Init();
res && mLogger->Init(true,true);
res && mEngine->GetMemoryManager()->Init(false);
}
else
return false;
/* Start Engine */
mEngine->Start();
/* Get logger */
mLogger = mEngine->GetLogger();
/* Run Memory Tests */
res &= RunMemoryTests();
if (res)
mLogger->LogInfo("TEST: TESTING SUCCESSFULL");
else
mLogger->LogError("TEST: TESTING FAILED");
return res;
}
/* Runs all memory tests */
bool TestManager::RunMemoryTests()
{
bool res = true;
res &= mMemTestMgr->AllocateTest();
res &= mMemTestMgr->ReferenceTest();
if (res)
mLogger->LogInfo("TEST: RunMemoryTests SUCCESSFULL");
else
mLogger->LogError("TEST: RunMemoryTests FAILED");
return res;
}
}
You cant call another constructor from the same class. I'd refactor the init code into a separate method and call it from both constructors:
namespace MyEngine
{
TestManager::TestManager()
{
Init(1);
}
TestManager::TestManager(uint64_t RepeatTimes)
{
Init(RepeatTimes);
}
void TestManager::Init(uint64_t RepeatTimes)
{
if (RepeatTimes>0)
mRepeatTimes = RepeatTimes;
else
{
mRepeatTimes = 1;
}
mEngine = Engine::GetEngine();
mMemTestMgr = new MemoryTestManager();
}
}
When you call TestManager(1); inside your TestManager::TestManager() constructor, you're creating another instance of TestManager, using the constructor TestManager::TestManager(uint64_t).
You can't do this on C++, you have to create either a init method, were you set the instance variables to whatever you want, or use optional parameters:
TestManager(uint64_t RepeatTimes = 0);
Then, if you create an instance of TestManager without arguments, you will be calling the TestManager::TestManager(uint64_t)constructor with 0 as the uint64_t argument.
you can't call a default constructor from a overloaded constructor. Why don't you simply create you object like this:
TestManager* testMgr = new TestManager(1);
Using a default argument (as per fontanini's answer) will do what you want in this case.
But if this is a simplified example and you really do want to delegate to another constructor, then that's not possible in C++03 - the line TestManager(1) just constructs a temporary object which goes unused (and the line will probably be optimized out unless the TestManager(uint64_t) constructor has side effects).
However, you can do what you're aiming for here with a C++11 compiler and the following syntax:
TestManager::TestManager() :
TestManager(1)
{
}