I have a function changeUserPassword() in user.cpp and I wanted to do a cppUnit test on it.
user.cpp
int User::changeUserPassword()
{
std::vector<user>::iterator it;
std::ifstream readFile("info.txt");
while(readFile >> userName >> password)
{
userDetails.push_back(user(userName,password));
}
readFile.close();
std::cout << "Please enter a user name that the password will be reset \n";
std::cin >> name;
it = std::find(userDetails.begin(),userDetails.end(),user(name,name));
if (it !=userDetails.end())
{
std::cout << "Please enter a new password" << std::endl;
std::cin >> newPassword;
it->setPassword(newPassword);
std::ofstream out("tempFile.txt");
for (it =userDetails.begin(); it !=userDetails.end(); it++) {
std::cout << it->getUserName() << " " << it->getPassword() << "\n";
out << it->getUserName() << " " << it->getPassword() << std::endl;
}
out.close();
remove("info.txt");
rename("tempfile.txt","info.txt");
}
else
{
it++;
}
return 0;
}
testcase.h
#ifndef TESTCASE_H
#define TESTCASE_H
#include "user.h"
#include <cppunit/TestCase.h>
#include <cppunit/extensions/HelperMacros.h>
class csci222TestCase : public CPPUNIT_NS::TestFixture {
CPPUNIT_TEST_SUITE(testcase);
CPPUNIT_TEST (testChangePassword);
CPPUNIT_TEST_SUITE_END();
public:
protected:
void testChangePassword(void);
private:
user testChangeUserPassword;
};
#endif
testcase.cpp
void testcase::testChangePassword(void) {
std::cout << "\n";
CPPUNIT_ASSERT_EQUAL(testChangeUserPassword.changeUserPassword(),0);
}
The thing is, I feel that the way I wrote my test case for changeUserPassword() isn't testing for anything. It's more like running the method and once it finished, it will return 0. How should I or what should I do to improve on the test case?
This function is not a good candidate for unit testing. It has file and user input for starters. You probably really only want to test the line
it->setPassword(newPassword);
which is actually what 'sets' the password, presumably. For that you would call the function in the unit test with a given password, then in turn do a getPassword() and see if it was changed to what you expected.
If you really want to test that function as-is, you would need to look into stubs and/or mock objects. For that you would need to refactor your code with some simple dependency injection, so you could swap the disk file I/O with some memory file I/O, for example. But I don't recommend this path.
To address the more conceptual issue that you have, your testChangePassword() function should just check that the password was changed. As it stands, all you're really testing for, in effect, is that the function doesn't throw an exception.
To sum up, your unit test should ideally be of the form:
user testuser;
testuser.setPassword( "Fred");
std::string pwd = testuser.getPassword();
CPPUNIT_ASSERT_EQUAL( "Fred", pwd);
In your case you should also try:
1. changing a password several times.
2. changing password to the same password.
3. changing a non existing password.
4. Changing the password on one with illegal characters.
5. Reading from a non-existing file.
6. Reading an invalid format of data from the file.
7. Check that you clean all fields of the your object unnecessary data when you complete the function.
Related
I have a two classes, one of which is a 'main' configuration, the other is a secondary configuration with a subset of some options from the main configuration. One of the 'main' configuration members is a vector of secondary configuration objects used to override the main configuration options if present. I can bind the 'main' configurations get methods to functions which I add to a vector and use to get those parameters in testing (not all options are tested every time, so I create a vector of set values which matches the vector of get methods which I compare.)
I would like to similarly bind the get methods from the secondary configurations, specifically the last (should be only) one in the vector, but I am unsure how to do this or if it is even possible. I have tried a number of tweaks that make sense to me, however I am starting to doubt if this would even be a good idea with the amount of convolution I am creating. If anyone could point me to how I would accomplish this, either by binding it in such a way that it calls the desired method from the first object in the vector or another way, that is what I am looking for. A heavily paired down example of what I am attempting to do is below.
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
class secConfig{
private:
double data;
public:
secConfig(double);
double get_data();
};
secConfig::secConfig(double indata){
data = indata;
}
double secConfig::get_data(){
return data;
}
class config{
private:
std::vector<secConfig> secConfigs;
double normalData;
public:
config(double, vector<secConfig>);
double getData();
vector<secConfig> getVecData();
};
config::config(double inData, vector<secConfig> inVec){
normalData = inData;
secConfigs = inVec;
}
double config::getData(){
return normalData;
}
vector<secConfig> config::getVecData(){
return secConfigs;
}
int main(int argc, char const *argv[])
{
secConfig initial(66.6);
vector<secConfig> inConfigs;
inConfigs.push_back(initial);
cout << "Inconfig raw data: " << initial.get_data() << endl;
cout << "Inconfig vector data: " << inConfigs.back().get_data() << endl;
config mainConfig(55.5, inConfigs);
cout << "Main config raw data: " << mainConfig.getData() << endl;
cout << "Main config internal vec data: " << mainConfig.getVecData().back().get_data() << endl;
vector<function<double()>> getvals;
getvals.push_back(bind(&config::getData, &mainConfig));
cout << "Main config bound data: " << getvals[0]() << endl;
// Something like: getvals.push_back(bind(&config::getVecData::back::get_data, &mainConfig));
// So I can: cout << "Secondary (vectorized) config data : " << getvals[1]() << endl;
return 0;
}
std::bind is rarely the best or easiest way to achieve something.
Use a lambda instead.
getvals.push_back( [&]{ return mainConfig.getVecData().back().get_data(); } );
I'm extremely new to C++ (even newer to OOP) and I'm doing my first project that doesn't take place within one .cpp file. I've run into a seemingly simple issue where my vector data seems to be disappearing.
Code chunk inside main.cpp's main function:
vector<Horse> HorseStable(horseAmount); // creating an vector of horse objects based on user input horseAmount
for (int i = 0; i < horseAmount; i++) // sets name for each horse and rider
{
string nameString = "";
string riderString = "";
cout << "Enter name for horse #" << (i + 1) << ": ";
cin >> nameString;
HorseStable[i].setName(nameString);
cout << "Enter name for rider of " << nameString << ": ";
cin >> riderString;
HorseStable[i].setRider(riderString);
system("cls");
}
HorseStable[0].printName(); // a test to see if the horse name stayed inside the vector (it did not)
Entire Horse.h file:
#pragma once
#include <iostream>
#include <string>
#include <stdlib.h>
#include <time.h>
class Horse
{
private:
std::string name;
std::string rider;
public:
// these three ints were supposed to be private, but I couldn't access
// maxRunningDistPerSecond as a displayHorse() function parameter from main
// maybe figuring out my first issue will help with this, as I was attempting
// HorseStable[0].displayHorse(maxRunningDistPerSecond)
int maxRunningDistPerSecond;
int distanceTraveled;
int racesWon;
Horse() // default constructor
{
std::string name = " ";
std::string rider = " ";
int maxRunningDistPerSecond = 100;
int distanceTraveled = 0;
int racesWon = 0;
};
int runASecond(int, int);
int sendToGate(int);
void displayHorse(int);
std::string setName(std::string); // sets the horse name based on user input from main.cpp variable
std::string printName(); // simply prints the horse name, I don't believe my issue is here
std::string setRider(std::string);
std::string printRider();
};
Code chunk inside Horse.cpp:
std::string Horse::setName(std::string nameString) // takes user input for horse name
{
Horse::name = nameString;
return std::string(nameString);
}
std::string Horse::printName() // prints the horse's name
{
return std::string(name);
}
setName() and getName() work perfectly within my for loop inside main.cpp, but all data seems to disappear when I attempt them after the loop ends. I've looked for hours for solutions, but had to revert to this stable build after nothing worked. I'm not very good with pointers and passing by reference, but these seem to be the only things that will work. Is it possible that I was using pointers wrong? Should I be creating a vector of Horse pointers, rather than a vector of actual Horse objects?
My other issue:
If you've noticed my public members that are supposed to be private in Horse.h, I cannot access them when private as parameters from functions called in main. This makes some sense, as my function call in main looked like this:
HorseStable[0].displayHorse(distanceTraveled)
I'm not sure how I could refer to each element of the vector within the Horse class, which seems like the only way distanceTraveled would be reachable as private. My professor wants the variables in question to be private, which makes this an issue. The user defines the amount of Horse objects, which means I can't just declare a few named Horses and simply displayHorse(distanceTraveled) them.
Function declaration from Horse.cpp:
void Horse::displayHorse(int distanceTraveled) // attempts to show a graphic of the race progress
{
if (distanceTraveled >= 50)
{
std::cout << "|-> |" << " " << name << ", ridden by " << rider;
}
else if (distanceTraveled >= 100)
{
std::cout << "|--> |" << " " << name << ", ridden by " << rider;
}
else if (distanceTraveled >= 150)
{
std::cout << "|---> |" << " " << name << ", ridden by " << rider;
} // this goes on up to 1000, but this is all that's necessary for posting
I apologize if my formatting isn't up to par, but this assignment has really been stressing me out. I've been understanding all the new material, but it always seems like pointers and referencing are the things that render my assignments unusable.
So basicly my questions include when to use parameters and when I dont need them.
I try to learn from examples and this one I can't fully understand:
I will add the questions to the part where I dont understand something after "//" on the right side of the line.
Maybe someone can give me a good explanation, what I need to do in which scenario or good sources where I can look this up on my own.
class Student with public attributes:
#include <iostream>
class Student
{
public:
int stud_ID;
char stud_Name[22];
int stud_Age;
};
function which I want included in int main():
void studentinformation(Student); //#1Why do I must include (Student) in this fuction? ->
// If I dont add this parameter in here, there is no connection ->
//to the function studentinformation(s) in int main.
//Why exactly is that the case ?
main function to get information:
int main(){
Student s;
std::cout<<"Type in ID:";
std::cin >> s.stud_ID;
std::cout<<"Type in youre Name:";
std::cin.ignore(); //
std::cin.getline(s.stud_Name, 22); //#2 Why is std::getline(std::cin, s.stud_Name) not working ?->
std::cout<<"Type in age:"; //#3 Or is there a better alternative ?
std::cin >> s.stud_Age;
studentinformation(s); //#4 Why do I must include the parameter s ?
return 0;
}
function to print information:
void studentinformation(Student s) // #5 Why do I must include the Parameters ?
{ std::cout<<" Student information:"<< std::endl;
std::cout<<" Student ID:" << s.stud_ID << std::endl;
std::cout<<" Name:" << s.stud_Name<< std::endl;
std::cout<<" Age:" << s.stud_Age<< std::endl;
}
studentinformation() is a free function with no connection to any instance of Student which is why you need to supply one as an argument.
std::getline() works on std::strings ...
... and you'd be doing yourself a favour if you changed char stud_Name[22]; to std::string stud_Name;.
For the same reason as in 1.
For the same reason as in 1. 1, 4 and 5 are questioning the same thing.
An alternative would be to make studentinformation() a Student member function instead. You could then call s.studentinformation(); to print info about that particular student.
class Student {
public:
int stud_ID;
std::string stud_Name; // suggested change
int stud_Age;
void studentinformation() const { // const since the object (this) won't be altered
std::cout << " Student information:" << '\n';
std::cout << " Student ID:" << stud_ID << '\n';
std::cout << " Name:" << stud_Name << '\n';
std::cout << " Age:" << stud_Age << '\n';
}
};
I'm still fairly new to C++ and programming so I might just be missing something big here.
I'm trying to create a chatbot for a library, deals with opening times ect and other things. I want the chatbot to be able to pickup key words in a input and then be able to call the right function that will be able to give some text back to them.
For example:
user: what time is the library open till?
//chatbot picks up the key word 'open' and returns the right function
chatbot: the libraries open between 6 and 5
It shouldn't be as hard as I am finding it to be able to get the chatbot to do this.
The function I'm having trouble with:
std::string GetKeywords(){
std::string KQuery = GetQuery();
std::vector<std::string> keywords{"open", "opening", "times", "close", "closing", "shut"};
if(std::find(keywords.begin(), keywords.end(), KQuery) != keywords.end()){
std::cout << "Library is open when I say it is" << std::endl;
}
return 0;
};
This is returning a memory error and is the only place in my code which throws an issue.
All my code:
#include <iostream>
#include <string>
#include <vector>
#include "FinalProject.hpp"
//introducing funtions
void PrintIntro();
std::string GetQuery();
std::string RunScripts();
std::string GetKeywords();;
// introducing chatbot
RunScript ChatBot;
int main(){
PrintIntro();
GetQuery();
GetKeywords();
};
void PrintIntro(){
//printing introductory text to ask the user for input
std::cout << "Hi, I'm Librarius, I'm here to help you with University library queries" << std::endl;
std::cout << "I can help you with the following: \n Spaces to study \n Opening times \n Taking out books \n Returning books\n" << std:: endl;
std::cout << "Ask away!" << std::endl;
return;
};
std::string GetQuery(){
//getting input from the user
std::string Query = "";
std::getline(std::cin, Query);
if(Query.empty()){
//checking to see if the user hasnt entered anything
std::cout << "Hey! Why didnt you enter anything?! I don't want to waste my time!" << std::endl;
};
return Query;
};
std::string GetKeywords(){
std::string KQuery = GetQuery();
std::vector<std::string> keywords{"open", "opening", "times", "close", "closing", "shut"};
if(std::find(keywords.begin(), keywords.end(), KQuery) != keywords.end()){
std::cout << "Library is open when I say it is" << std::endl;
}
return 0;
};
//using the input got from the user to decide which script to run
//TODO analyse the users keywords and decide on a script to run
//TODO return an appropriate script
Thanks for your help!
The problem with
std::find(keywords.begin(), keywords.end(), KQuery)
is it is going to see if the entire string in KQuery matches one of your keywords. Since KQuery has a sentence in it, it isn't going to find a match. What you need to do is loop through all the keywords and see if KQuery.find(keyword) returns a valid result.
You can do that using std::find_if and a lambda like
std::find_if(keywords.begin(), keywords.end(),
[&](auto const& keyword){ return KQuery.find(keyword) != std::string::npos; });
This will return an iterator to the first keyword it finds in KQuery or keywords.end() if none of the keywords are found.
I have been trying to make a brute-force program in C++, for a school project, but I want to make the password you enter censored, so instead of like password it would be **
PS it's an console application
This is my C++ Code:
#include <iostream>
#include <string>
using namespace std;
char chars[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','W','R','S','T','U','V','W','X','Y','Z'};
string t;
void checkPassword(string password);
void recurse(int width, int position, string baseString);
int main() {
cout << "Enter a Password: " << endl;
cin >> t;
int maxChars = 13;
for(int i=0;i<maxChars+1;i++) {
cout << "checking passwords width [" << i << "]..." << endl;
recurse(i,0,"");
}
return 0;
}
void recurse(int width, int position, string baseString) {
for(int i=0;i<70;i++) {
if (position < width-1) {
recurse(width, position + 1, baseString+chars[i]);
}
checkPassword(baseString+chars[i]);
}
}
void checkPassword(string password) {
if (password==t) {
cout << "Match Found: " << password << "" << endl;
return;
}
}
I have tried a lot but I can't seem to get it working, thanks in advance.
A console program doesn't have the capabilities to do this. If you're working on a Windows machine and don't need any cross-platform portability, you may be able to get away with using the non-standard conio.h library's getch() function to simulate cin while replacing the characters. But I honestly recommend against a roundabout approach like that. If you really need the censorship of the password, I suggest that you either turn the program into a GUI application or ask the user to type their password into a file and then give the filename (so that it doesn't appear onscreen as directly).