C++ CppUnit Test (CPPUNIT_ASSERT) - c++

I'm trying to do up a screen scraping assignment. My cpp works, but I don't know how to integrate my unit testing. I tried to do a bool check unit test for the file validity but it's giving me this error:
error: cannot call member function 'bool ScreenScrape::getFile()' without object
screenscrape.cpp:
#include "screenscrape.h"
using namespace std;
int main()
{
ScreenScrape ss;
int choice;
...
...
ss.matchPatternTest();
}
screenscrape.h:
class ScreenScrape
{
public:
ScreenScrape();
void parserTest(int choice);
void matchPatternTest();
void setIndexValue(string data, string IndexName);
void setIndexChange(string data);
void setIndexPercent(string data);
void setIndexDate(string data);
bool getFile();
private:
string IndexName;
string IndexValue;
string IndexChange;
string IndexPercent;
string IndexVID;
string IndexCID;
string IndexPID;
string IndexDate;
};
bool ScreenScrape::getFile()
{
string file1 = "yahoofinance.htm";
char* file2 = new char [file1.size()+1]; // parse file for c string conversion
strcpy(file2, file1.c_str()); // converts to c string
ifstream fin;
fin.open(file2);
if(fin.good())
return true;
else
return false;
}
screenscrapetest.cpp:
#include "screenscrapetest.h"
#include "screenscrape.h"
CPPUNIT_TEST_SUITE_REGISTRATION (ScreenScrapeTest);
void ScreenScrapeTest::fileTest()
{
CPPUNIT_ASSERT(ScreenScrape::getFile()); // test file validity
}
screenscrapetest.h:
#ifndef _SCREENSCRAPETEST_H
#define _SCREENSCRAPETEST_H
#include <cppunit/TestCase.h>
#include <cppunit/extensions/HelperMacros.h>
#include "screenscrape.h"
class ScreenScrapeTest : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE (ScreenScrapeTest);
CPPUNIT_TEST (fileTest);
CPPUNIT_TEST_SUITE_END ();
public:
void fileTest();
};
#endif
I tried to declare "ScreenScrape ss;" under screenscrapetest.h, use an object (ss) to call getFile() but it's giving me multiples of this error:
/home/user/NetBeansProjects/Assignment1/screenscrape.h:259: multiple definition of `ScreenScrape::getFile()'
I only want to check for file validity with unit testing. Any help will be appreciated.
Thanks in advance!
Regards,
Wallace

bool ScreenScrape::getFile() is not static, so cannot be called as a static function. You'll need to either (a) declare it as static or (b) create an instance of ScreenScrape and call getFile() from it.
Looking at the code, it's not obvious why this function is a method of the class but perhaps it's still in the early stages of development. It can also be refactored to remove lots of redundant code:
bool ScreenScrape::getFile()
{
std::ifstream fin("yahoofinance.htm");
return fin.good();
}
Don't forget your include guards in screenscrape.h:
#ifndef SCREENSCRAPE_H
#define SCREENSCRAPE_H
// Class declaration here...
#endif//ndef SCREENSCRAPE_H
And consider moving the implementation of getFile to the cpp source file. These two steps will prevent you getting the "multiple declaration" errors.
This will fix your compilation errors, but checking for file validity is not a responsibility of a unit test. Unit tests should not interact with the filesystem.

If you're going to be calling ScreenScrape::getfile()rather than ss.getfile(), then getfile() needs be defined as static. The error you're getting is because non-static methods need to be called on a specific object.
It's difficult to track down the error with your version that defines a ScreenScrape object and then uses that to call getfile(); you obviously haven't included all the relevant code since your screenscrape.h file doesn't have 259 lines, and you also haven't shown the revised code in which you "use an object (ss) to call getFile()".

Related

C++ Beginner : calling default vs custom constructor

Beginner here - but i was uncertain what exactly to search for this (presumably common) question.
I am working on a program where I have a given class (Dictionary). I am supposed to make a concrete class (Word) which implements Dictionary. I should mention that I am not to change anything in Dictionary.
After making a header file for Word, I define everything in word.cpp.
I am unsure if I am doing this correctly, but I make the constructor read from a given file, and store the information in a public member of Word.
(I understand that the vectors should be private, but I made it public to get to the root of this current issue)
dictionary.h
#ifndef __DICTIONARY_H__
#define __DICTIONARY_H__
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
class Dictionary
{
public:
Dictionary(istream&);
virtual int search(string keyword, size_t prefix_length)=0;
};
#endif /* __DICTIONARY_H__ */
word.h
#ifndef __WORD_H__
#define __WORD_H__
#include "dictionary.h"
class Word : public Dictionary{
public:
vector<string> dictionary_words;
vector<string> source_file_words;
Word(istream &file);
int search(string keyword, size_t prefix_length);
void permutation_search(string keyword, string& prefix, ofstream& fout, int& prefix_length);
};
#endif /* __WORD_H__*/
word.cpp
#include "word.h"
Word(istream& file) : Dictionary(istream& file)
{
string temp;
while (file >> temp)
{
getline(file,temp);
dictionary_words.push_back(temp);
}
}
In word.cpp, on the line "Word::Word(istream& file)", I get this error :' [Error] no matching function for call to 'Dictionary::Dictionary()'.
I've been told this is error is due to "Word's constructor invoking Dictionary's ", but I still don't quite grasp the idea well. I am not trying to use Dictionary's constructor, but Word's.
If anyone has an idea for a solution, I would also appreciate any terms related to what is causing this issue that I could look up - I wasn't even sure how to title the problem.
Your child class should invoke parent constructor, because parent object are constructed before child. So you should write something like:
Word::Word(isteam& file) : Dictionary(file)
{
...
}
Seems its better described here What are the rules for calling the superclass constructor?

C++ class to read a text file - getting errors

I have the following code to read a text file using a class definition. I created the TermGrade.h file and the TermGrade.cpp file. But I get few errors:
In the TermGrade.h file I get the warning that it cannot find a definition for any of the defined functions ( Readdata, MidsemesterScore, FinalScore and LetterGrade) even though I have them defined in the .cpp file.
However, the main problem is that in the TermGrade.cpp file I get the error "Error:No instance of overloaded function "getline" matches the argument list" and it also complains that identifier "inLine" is undefined, but it does not complain about inLine in the next statement, but that statement says that both
dataLines[lineNumber] are undefined! Do I need to define these variables in the .cpp file? Any help would be greatly appreciated.
Thank you,
Bill.
// TermGrade.h file
#ifndef TERMGRADE_H
#define TERMGRADE_H
#include <string>
#include<iostream>
#include<fstream>
using namespace std;
class TermGrade {
public:
TermGrade(string fileName) {};
string StudentID;
int assignments;
int exam1;
int exam2;
int final;
bool records = true;
private:
string inLine;
string dataLines[100];
int lineNumber = 0;
bool Readdata(istream& in); // Read line of data from input file
double MidsemesterScore() const; // Calculates average
double FinalScore() const; // Calculates average
char LetterGrade() const; // Determines grade
}; // end class Termgrade
#endif
// TermGrade.cpp file
#include "TermGrade.h" // TermGrade class definition
#include<iostream>
#include<fstream>
TermGrade::TermGrade(string fileName) {
ifstream infile;
infile.open(fileName);
}
bool Readdata(istream& infile)
{
if (!infile.eof)
{
getline(infile, inLine);
dataLines[lineNumber] = inLine;
return true;
}
return false;
}
double MidsemesterScore()
{
return 0.0;
}
double FinalScore()
{
return 0.0;
}
char LetterGrade()
{
return 'a';
}
In the TermGrade.h file I get the warning that it cannot find a
definition for any of the defined functions ( Readdata,
MidsemesterScore, FinalScore and LetterGrade) even though I have them
defined in the .cpp file.
No, you don't have them defined in the .cpp file. You do not have, for example a definition of TermGrade::Readdata method. That method is not defined anywhere. You do have a function called Readdata in there, but that has nothing to do, whatsoever, with the TermGrade::Readdata method.
Regarding a few of the other errors you're getting:
You are calling a function called getline(), however you have not defined that function anywhere, and that's why you are getting that compiler error. Perhaps you meant to refer to the std::getline() function, from the C++ library, if so then that's what you should be referring to.
Also, you are passing a reference to a class called istream, unfortunately you did not define this class anywhere. If you meant to refer to the std::istream class, then you should've referenced it, as such.
However, the std::istream class does not have a member called eof. It does have an eof() method, though.

How to make a variable available to multiple .cpp files using a class?

This question has derived from this one.
I have a working program which must be split into multiple parts. In this program is needed to use a variable (now it's a GTK+ one :P) many times in parts of the program that will end up in separated .cpp files.
So, I made a simple example to understand how to make variables available to the program parts. A modified version of the previous code would be:
#include <iostream>
using namespace std;
int entero = 10;
void function()
{
cout<<entero<<endl;
//action1...;
}
void separated_function()
{
cout<<entero<<endl;
//action2...;
}
int main( int argc, char *argv[] )
{
function();
separated_function();
cout<<entero<<endl;
//something else with the mentioned variables...;
return 0;
}
It is needed to split the code correctly, to have function(), another_function() and main() in separated .cpp files,and make entero avaliable to all of them... BUT:
In the previous question #NeilKirk commented:Do not use global variables. Put the required state into a struct or class, and pass it to functions as necessary as a parameter (And I also have found many web pages pointing that is not recommended to use global variables).
And, as far I can understand, in the answer provided by #PaulH., he is describing how to make variables avaliable by making them global.
This answer was very useful, it worked fine not only with char arrays, but also with ints, strings and GTK+ variables (or pointers to variables :P).
But since this method is not recommended, I would thank anyone who could show what would be the correct way to split the code passing the variables as a function parameter or some other method more recommended than the - working - global variables one.
I researched about parameters and classes, but I'm a newbie, and I messed the code up with no good result.
You need to give the parameter as a reference if you want the same comportement as a global variable
#include <iostream>
using namespace std;
// renamed the parameter to avoid confusion ('entero' is valid though)
void function(int &ent)
{
cout<<ent<<endl;
++ent; // modify its value
//action1...;
}
void separated_function(int &ent)
{
cout<<ent<<endl;
++ent; // modify its value again
//action2...;
}
int main( int argc, char *argv[] )
{
int entero = 10; // initializing the variable
// give the parameter by reference => the functions will be able to modify its value
function(entero);
separated_function(entero);
cout<<entero<<endl;
//something else with the mentioned variables...;
return 0;
}
output:
10
11
12
Defining a class or struct in a header file is the way to go, then include the header file in all source files that needs the classes or structures. You can also place function prototypes or preprocessor macros in header files if they are needed by multiple source files, as well as variable declarations (e.g. extern int some_int_var;) and namespace declarations.
You will not get multiple definition errors from defining the classes, because classes is a concept for the compiler to handle, classes themselves are never passed on for the linker where multiple definition errors occurs.
Lets take a simple example, with one header file and two source files.
First the header file, e.g. myheader.h:
#ifndef MYHEADER_H
#define MYHEADER_H
// The above is called include guards (https://en.wikipedia.org/wiki/Include_guard)
// and are used to protect the header file from being included
// by the same source file twice
// Define a namespace
namespace foo
{
// Define a class
class my_class
{
public:
my_class(int val)
: value_(val)
{}
int get_value() const
{
return value_;
}
void set_value(const int val)
{
value_ = val;
}
private:
int value_;
};
// Declare a function prototype
void bar(my_class& v);
}
#endif // MYHEADER_H
The above header file defines a namespace foo and in the namespace a class my_class and a function bar.
(The namespace is strictly not necessary for a simple program like this, but for larger projects it becomes more needed.)
Then the first source file, e.g. main.cpp:
#include <iostream>
#include "myheader.h" // Include our own header file
int main()
{
using namespace foo;
my_class my_object(123); // Create an instance of the class
bar(my_object); // Call the function
std::cout << "In main(), value is " << my_object.get_value() << '\n';
// All done
}
And finally the second source file, e.g. bar.cpp:
#include <iostream>
#include "myheader.h"
void foo::bar(foo::my_class& val)
{
std::cout << "In foo::bar(), value is " << val.get_value() << '\n';
val.set_value(456);
}
Put all three files in the same project, and build. You should now get an executable program that outputs
In foo::bar(), value is 123
In main(), value is 456
I prefer to provide a functional interface to global data.
.h file:
extern int get_entero();
extern void set_entero(int v);
.cpp file:
static int entero = 10;
int get_entero()
{
return entero;
}
void set_entero(int v)
{
entero = v;
}
Then, everywhere else, use those functions.
#include "the_h_file"
void function()
{
cout << get_entero() << endl;
//action1...;
}
void separated_function()
{
cout << get_entero() << endl;
//action2...;
}
int main( int argc, char *argv[] )
{
function();
separated_function();
cout<< get_entero() <<endl;
//something else with the mentioned variables...;
return 0;
}
If you do not plan to modify the variable, it is generally ok to make it global. However, it is best to declare it with the const keyword to signal the compiler that it should not be modified, like so:
const int ENTERO = 10;
If you are using multiple cpp files, also consider using a header file for your structures and function declarations.
If you are planning on modifying the variable, just pass it around in function parameters.

setter in class won't set variable

I'm currently trying to make a game in C++. In my code I'm trying to nest my variables so that my main doesn't have a lot of includes. My problem right now though is that the value of my variables in my class aren't changing. Stepping through the code it shows it setting the value, but it doesn't work. Anyone know what's going on? Thank you in advance.
This is what I have so far:
Location.h
#ifndef LOCATION_H
#define LOCATION_H
#include <string>
class Location
{
public:
Location(void);
Location(std::string name);
~Location(void);
std::string GetName();
void SetName(std::string value);
private:
std::string m_Name
};
#endif
Location.cpp
#include "Location.h"
Location::Location(void): m_Name("") {}
Location::Location(std::string name): m_Name(name) {}
Location::~Location(void)
{
}
std::string Location::GetName()
{return m_Name;}
void Location::SetName(std::string value){m_Name = value;}
PlayerStats.h
#ifndef PLAYERSTATS_H
#define PLAYERSTATS_H
#include "Location.h"
class PlayerStats
{
public:
PlayerStats(void);
~PlayerStats(void);
Location GetLocation();
void SetLocation(Location location);
private:
Location m_Location;
};
#endif
PlayerStats.cpp
#include "PlayerStats.h"
PlayerStats::PlayerStats(void): m_Location(Location()) {}
PlayerStats::~PlayerStats(void)
{
}
Location PlayerStats::GetLocation(){return m_Location;}
void PlayerStats::SetLocation(Location location){m_Location = location;}
main.cpp
#include <iostream>
#include "PlayerStats.h"
using namespace std;
PlayerStats playerStats = PlayerStats();
int main()
{
playerStats.GetLocation().SetName("Test");
cout<< playerStats.GetLocation().GetName()<<endl;
return 0;
}
Your immediate issue is that
Location GetLocation();
returns a copy of the location, so when you call SetName here:
playerStats.GetLocation().SetName("Test");
You're changing the name of the temporary copy, and the change is lost as soon as the semicolon is hit.
More broadly, this kind of design (nesting classes and nesting includes so that main doesn't have a lot of includes, and using a.b.c() style code to access nested members) isn't great C++ style:
Having a bunch of source files that (transitively) include a bunch of header files means that changing a single header file will trigger recompilations of a bunch of source files. Compile times can be a significant issue in larger C++ projects, so reducing compile times by controlling #include's is important. Read up on "forward declarations" for more information.
Writing code like a.b.c() is considered bad object-oriented design, because it reduces encapsulation: not only does the caller have to know about a's details, it has to know about b's also. Sometimes this is the most expedient way to write code, but it's not something to be blindly done just to reduce #include's. Read up on "Law of Demeter" for more information.
If you want to set the result of playerStats.GetLocation(), you could make GetLocation() pass-by-reference (use ampersand, &, on the return argument). Otherwise you are just setting values in a temporary copy of PlayerStats::m_Location.
Alternatively, you could use the SetLocation() function.

State Machines, Sub-Classes, and Function Pointers

I'm having trouble implementing a state machine for class. I keep getting the errors:
state.cpp:5: error: have0 was not declared in this scope
state.cpp:10: error: redefinition of State* Have0State::process(std::string)
state.h:18: error: virtual State* Have0State::process(std::string) previously defined here
I'm trying to get the Have0State to work before I continue onto the rest of the machine, hence the sparse code.
state.h:
#ifndef STATE_H
#define STATE_H
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <iostream>
class State{
public:
State(){};
virtual State* process(std::string input) = 0;
};
class Have0State: public State {
public:
Have0State():State(){};
virtual State* process(std::string input);
}have0;
#endif
state.cpp:
#include "state.h"
using namespace std;
State *currentState = &have0;
State* Have0State::process(string input){
if(input == "quarter"){
cout << "cool" << endl;
}
return &have0;
}
int main(int argc, char** argv) {
string input;
//get input
cin >> input;
while (input != "exit") {
currentState = currentState->process(input);
//get input
cin >> input;
}
return 0;
};
I've tried defining the process function as Have0State::State::process(string input) but that didn't work either. Any clarification on how function pointers are supposed to work, especially in the context of subclass member functions, I would greatly appreciate it.
EDIT: Also, what exactly is the have0 declaration at the end of the Have0State class declaration in the state.h file? It doesn't have an explicitly stated type; is it implied that it is of type Have0State??
There aren't any function pointers in your example. Also, like Marciej, I am able to compile (and run) this code.
But, since you asked, the 'have0' declaration simply declares an instance of the class. A class definition can be followed by 0 or more of these declarations (as well as initializers):
class Thing {...} one, another, many[3] = { Thing(1), Thing(2), Thing(3) };
the same as for any other type:
int counter = 0, flag = 0x80, limit = 500;
The possibility of this optional declarator list is why class, struct, union, and enum definitions must be followed with a semi-colon (to terminate the list).
But, as Karthik said, defining a variable in a header will cause "duplicate definition" errors at link time, if the header is included in more than one .cpp file. IMO it's fine though to use this technique to define and declare private objects in a .cpp file (rather than a .h file).