This site is from a past semester! The current version will be here when the new semester starts.
CS2103/T 2020 Aug-Dec
  • Full Timeline
  • Week 1 [Mon, Aug 10th]
  • Week 2 [Fri, Aug 14th]
  • Week 3 [Fri, Aug 21st]
  • Week 4 [Fri, Aug 28th]
  • Week 5 [Fri, Sep 4th]
  • Week 6 [Fri, Sep 11th]
  • Week 7 [Fri, Sep 18th]
  • Week 8 [Fri, Oct 2nd]
  • Week 9 [Fri, Oct 9th]
  • Week 10 [Fri, Oct 16th]
  • Week 11 [Fri, Oct 23rd]
  • Week 12 [Fri, Oct 30th]
  • Week 13 [Fri, Nov 6th]
  • Textbook
  • Admin Info
  • Dashboards
  •  Individual Project (iP):
  • Individual Project Info
  • iP Upstream Repo
  • iP Showcase
  • iP Code Dashboard
  • iP Progress Dashboard

  •  Team Project (tP):
  • Team Project Info
  • Addressbook-level3
  • Team List
  • tP Code Dashboard
  • tP Progress Dashboard
  • Report Bugs
  • Forum
  • Gitter (Chat)
  • Instructors
  • Announcements
  • Files
  • Tutorial Schedule
  • Java Coding Standard
  • Git Conventions
  • Forum Activities Dashboard
  • Participation Dashboard
  • Week 2 [Fri, Aug 14th] - Topics

    • [W2.1a] Software Engineering → Introduction → Pros and cons

    • [W2.2] SDLC Process Models: Basics
    • [W2.2a] Project Management → SDLC Process Models → Introduction → What

    • [W2.2b] Project Management → SDLC Process Models → Introduction → Sequential models

    • [W2.2c] Project Management → SDLC Process Models → Introduction → Iterative models

    • [W2.3] RCS: Revision History
    • [W2.3a] Project Management → Revision Control → What

    • [W2.3b] Project Management → Revision Control → Repositories

    • [W2.3c] Tools → Git and GitHub → init: Getting started

    • [W2.3d] Project Management → Revision Control → Saving history

    • [W2.3e] Tools → Git and GitHub → commit: Saving changes to history

    • [W2.3f] Tools → Git and GitHub → Omitting files from revision control

    • [W2.3g] Project Management → Revision Control → Using history

    • [W2.3h] Tools → Git and GitHub → tag: Naming commits

    • [W2.3i] Tools → Git and GitHub → diff: Comparing revisions

    • [W2.3j] Tools → Git and GitHub → checkout: Retrieving a specific revision

    • [W2.3k] Tools → Git and GitHub → stash: Shelving changes temporarily : OPTIONAL

    • [W2.4] RCS: Remote Repos
    • [W2.4a] Project Management → Revision Control → Remote repositories

    • [W2.4b] Tools → Git and GitHub → clone: Copying a repo

    • [W2.4c] Tools → Git and GitHub → pull, fetch: Downloading data from other repos

    • [W2.4d] Tools → Git and GitHub → Fork: Creating a remote copy

    • [W2.4e] Tools → Git and GitHub → push: Uploading data to other repos

    • [W2.5] IDEs: Basic Features
    • [W2.5a] Implementation → IDEs → What

    • [W2.5b] Tools → IntelliJ IDEA → Project setup

    • [W2.6] Automated Testing of Text UIs
    • [W2.6a] Quality Assurance → Testing → Introduction → What

    • [W2.6b] Quality Assurance → Testing → Regression Testing → What

    • [W2.6c] Quality Assurance → Testing → Test Automation → What

    • [W2.6d] Quality Assurance → Testing → Test Automation → Automated testing of CLI applications


    Guidance for the item(s) below:

    Given this is a first course in SE, tradition demands that we start by defining the subject. However, we are not going to spend a lot of time going through definitions of SE. Instead, let's look at an extract from the very first chapter of a very famous SE book, with the aim of providing some inspiration but also an appreciation of the challenges ahead.

    [W2.1] SE: Intro

    W2.1a

    Software Engineering → Introduction → Pros and cons

    Can explain pros and cons of software engineering

    Software engineering: Software Engineering is the application of a systematic, disciplined, quantifiable approach to the development, operation, and maintenance of software" -- IEEE Standard Glossary of Software Engineering Terminology

    The following description of the Joys of the Programming Craft was taken from Chapter 1 of the famous book The Mythical Man-Month, by Frederick P. Brooks.

    Why is programming fun? What delights may its practitioner expect as his reward?

    First is the sheer joy of making things. As the child delights in his mud pie, so the adult enjoys building things, especially things of his own design. I think this delight must be an image of God's delight in making things, a delight shown in the distinctness and newness of each leaf and each snowflake.

    Second is the pleasure of making things that are useful to other people. Deep within, you want others to use your work and to find it helpful. In this respect the programming system is not essentially different from the child's first clay pencil holder "for Daddy's office."

    Third is the fascination of fashioning complex puzzle-like objects of interlocking moving parts and watching them work in subtle cycles, playing out the consequences of principles built in from the beginning. The programmed computer has all the fascination of the pinball machine or the jukebox mechanism, carried to the ultimate.

    Fourth is the joy of always learning, which springs from the nonrepeating nature of the task. In one way or another the problem is ever new, and its solver learns something: sometimes practical, sometimes theoretical, and sometimes both.

    Finally, there is the delight of working in such a tractable medium. The programmer, like the poet, works only slightly removed from pure thought-stuff. He builds his castles in the air, from air, creating by the exertion of the imagination. Few media of creation are so flexible, so easy to polish and rework, so readily capable of realizing grand conceptual structures....

    Yet the program construct, unlike the poet's words, is real in the sense that it moves and works, producing visible outputs separate from the construct itself. It prints results, draws pictures, produces sounds, moves arms. The magic of myth and legend has come true in our time. One types the correct incantation on a keyboard, and a display screen comes to life, showing things that never were nor could be.

    Programming then is fun because it gratifies creative longings built deep within us and delights sensibilities you have in common with all men.

    Not all is delight, however, and knowing the inherent woes makes it easier to bear them when they appear.

    First, one must perform perfectly. The computer resembles the magic of legend in this respect, too. If one character, one pause, of the incantation is not strictly in proper form, the magic doesn't work. Human beings are not accustomed to being perfect, and few areas of human activity demand it. Adjusting to the requirement for perfection is, I think, the most difficult part of learning to program.

    Next, other people set one's objectives, provide one's resources, and furnish one's information. One rarely controls the circumstances of his work, or even its goal. In management terms, one's authority is not sufficient for his responsibility. It seems that in all fields, however, the jobs where things get done never have formal authority commensurate with responsibility. In practice, actual (as opposed to formal) authority is acquired from the very momentum of accomplishment.

    The dependence upon others has a particular case that is especially painful for the system programmer. He depends upon other people's programs. These are often maldesigned, poorly implemented, incompletely delivered (no source code or test cases), and poorly documented. So he must spend hours studying and fixing things that in an ideal world would be complete, available, and usable.

    The next woe is that designing grand concepts is fun; finding nitty little bugs is just work. With any creative activity come dreary hours of tedious, painstaking labor, and programming is no exception.

    Next, one finds that debugging has a linear convergence, or worse, where one somehow expects a quadratic sort of approach to the end. So testing drags on and on, the last difficult bugs taking more time to find than the first.

    The last woe, and sometimes the last straw, is that the product over which one has labored so long appears to be obsolete upon (or before) completion. Already colleagues and competitors are in hot pursuit of new and better ideas. Already the displacement of one's thought-child is not only conceived, but scheduled.

    This always seems worse than it really is. The new and better product is generally not available when one completes his own; it is only talked about. It, too, will require months of development. The real tiger is never a match for the paper one, unless actual use is wanted. Then the virtues of reality have a satisfaction all their own.

    Of course the technological base on which one builds is always advancing. As soon as one freezes a design, it becomes obsolete in terms of its concepts. But implementation of real products demands phasing and quantizing. The obsolescence of an implementation must be measured against other existing implementations, not against unrealized concepts. The challenge and the mission are to find real solutions to real problems on actual schedules with available resources.

    This then is programming, both a tar pit in which many efforts have floundered and a creative activity with joys and woes all its own. For many, the joys far outweigh the woes....

    [Text and book cover source: Wikipedia]

    [Fred Brooks photo source]

    The Mythical Man-Month: Essays on Software Engineering is a book on software engineering and project management by Fred Brooks, whose central theme is that "adding manpower to a late software project makes it later". This idea is known as Brooks's law, and is presented along with the second-system effect and advocacy of prototyping.

    Compare Software Engineering with Civil Engineering in terms of how work products in CE (i.e. buildings) differ from those of SE (i.e. software).

    Buildings Software
    Visible, tangible Invisible, intangible
    Wears out over time Does not wear out
    Change is limited by physical restrictions (e.g. difficult to remove a floor from a high rise building) Change is not limited by such restrictions. Just change the code and recompile.
    Creating an exact copy of a building is impossible. Creating a near copy is almost as costly as creating the original. Any number of exact copies can be made with near zero cost.
    Difficult to move. Easily delivered from one place to another.
    Many low-skilled workers following tried-and-tested procedures. No low-skilled workers involved. Workers have more freedom to follow their own procedures.
    Easier to assure quality (just follow accepted procedure). Not easy to assure quality.
    Majority of the workforce has to be on location. Can be built by people who are not even in the same country.
    Raw materials are costly, costly equipment required. Almost free raw materials and relatively cheap equipment.
    Once construction is started, it is hard to do drastic changes to the design. Building process is very flexible. Drastic design changes can be done, although costly
    A lot of manual and menial labor involved. Most work involves highly-skilled labor.
    Generally robust. E.g. removing a single brick is unlikely to destroy a building. More fragile than buildings. A single misplaced semicolon can render the whole system useless.

    Comment on this statement: Building software is cheaper and easier than building bridges (all we need is a PC!).

    Depends on the size of the software. Manpower required for software is very costly. On the other hand, we can create very valuable software (e.g. an iPhone application that can make million dollars in a month) with just a PC and a few days of work!

    Justify this statement: Coding is still a ‘design’ activity, not a ‘manufacturing’ activity. You may use a comparison (or an analogy) of Software Engineering versus Civil Engineering to argue this point.

    Arguments to support this statement:

    • If coding is a manufacturing activity, we should be able to do it using robotic machines (just like in the car industry) or low-skilled laborers (like in the construction industry).
    • If coding is a manufacturing activity, we wouldn’t be changing it so much after we code software. But if the code is in fact a ‘design’, yes, we would fiddle with it until we get it right.
    • Manufacturing is the process of building a finished product based on the design. Code is the design. Manufacturing is what is done by the compiler (fully automated).

    However, the type of ‘design’ that occurs during coding is at a much lower level than the ‘design’ that occurs before coding.

    List some (at least three each) pros and cons of Software Engineering compared to other traditional Engineering careers.

    • a. Need for perfection when developing software
    • b. Requiring some amount of tedious, painstaking labor
    • c. Ease of copying and transporting software makes it difficult to keep track of versions
    • d. High dependence on others
    • e. Seemingly never ending effort required for testing and debugging software
    • f. Fast moving industry making our work obsolete quickly

    (c)

    Guidance for the item(s) below:

    Broadly speaking, there are two approaches to doing a software project. Those two approaches are also highly relevant to the way this module is run, and how it is different from most SE modules elsewhere.

    Let's learn about those two approaches early so that we can better understand how this module works.

    [W2.2] SDLC Process Models: Basics

    W2.2a

    Project Management → SDLC Process Models → Introduction → What

    Can explain SDLC process models

    Software development goes through different stages such as requirements, analysis, design, implementation and testing. These stages are collectively known as the software development life cycle (SDLC). There are several approaches, known as software development life cycle models (also called software process models), that describe different ways to go through the SDLC. Each process model prescribes a "roadmap" for the software developers to manage the development effort. The roadmap describes the aims of the development stage(s), the artifacts or outcome of each stage, as well as the workflow i.e. the relationship between stages.

    W2.2b

    Project Management → SDLC Process Models → Introduction → Sequential models

    Can explain sequential process models

    The sequential model, also called the waterfall model, models software development as a linear process, in which the project is seen as progressing steadily in one direction through the development stages. The name waterfall stems from how the model is drawn to look like a waterfall (see below).

    When one stage of the process is completed, it should produce some artifacts to be used in the next stage. For example, upon completion of the requirements stage, a comprehensive list of requirements is produced that will see no further modifications. A strict application of the sequential model would require each stage to be completed before starting the next.

    This could be a useful model when the problem statement is well-understood and stable. In such cases, using the sequential model should result in a timely and systematic development effort, provided that all goes well. As each stage has a well-defined outcome, the progress of the project can be tracked with relative ease.

    The major problem with this model is that the requirements of a real-world project are rarely well-understood at the beginning and keep changing over time. One reason for this is that users are generally not aware of how a software application can be used without prior experience in using a similar application.

    W2.2c

    Project Management → SDLC Process Models → Introduction → Iterative models

    Can explain iterative process models

    The iterative model (sometimes called iterative and incremental) advocates having several iterations of SDLC. Each of the iterations could potentially go through all the development stages, from requirements gathering to testing & deployment. Roughly, it appears to be similar to several cycles of the sequential model.

    In this model, each of the iterations produces a new version of the product. Feedback on the new version can then be fed to the next iteration. Taking the Minesweeper game as an example, the iterative model will deliver a fully playable version from the early iterations. However, the first iteration will have primitive functionality, for example, a clumsy text based UI, fixed board size, limited randomization, etc. These functionalities will then be improved in later releases.

    The iterative model can take a breadth-first or a depth-first approach to iteration planning.

    • breadth-first: an iteration evolves all major components in parallel e.g., add a new feature fully, or enhance an existing feature.
    • depth-first: an iteration focuses on fleshing out only some components e.g., update the backend to support a new feature that will be added in a future iteration.

    Most projects use a mixture of breadth-first and depth-first iterations i.e., an iteration can contain some breadth-first work as well as some depth-first work.

    Guidance for the item(s) below:

    This week, you are starting your individual project (iP). As you are adding code to the iP in rapid succession, you'll need a way to keep track of all the changes you do. The tool we are going to use for that is called Git, and we need to learn Git basics pretty quickly.

    Let's jump in and learn how to get started using Git in your own computer. Yes, we are now switching our focus to the project management aspect of SE.

    [W2.3] RCS: Revision History

    Guidance for the item(s) below:

    First, let's learn a bit about tracking the change history of a project in general, at a higher level.

    W2.3a

    Project Management → Revision Control → What

    Can explain revision control

    Revision control is the process of managing multiple versions of a piece of information. In its simplest form, this is something that many people do by hand: every time you modify a file, save it under a new name that contains a number, each one higher than the number of the preceding version.

    Manually managing multiple versions of even a single file is an error-prone task, though, so software tools to help automate this process have long been available. The earliest automated revision control tools were intended to help a single user to manage revisions of a single file. Over the past few decades, the scope of revision control tools has expanded greatly; they now manage multiple files, and help multiple people to work together. The best modern revision control tools have no problem coping with thousands of people working together on projects that consist of hundreds of thousands of files.

    Revision control software will track the history and evolution of your project, so you don't have to. For every change, you'll have a log of who made it; why they made it; when they made it; and what the change was.

    Revision control software makes it easier for you to collaborate when you're working with other people. For example, when people more or less simultaneously make potentially incompatible changes, the software will help you to identify and resolve those conflicts.

    It can help you to recover from mistakes. If you make a change that later turns out to be an error, you can revert to an earlier version of one or more files. In fact, a really good revision control tool will even help you to efficiently figure out exactly when a problem was introduced.

    It will help you to work simultaneously on, and manage the drift between, multiple versions of your project. Most of these reasons are equally valid, at least in theory, whether you're working on a project by yourself, or with a hundred other people.

    -- [adapted from bryan-mercurial-guide]

    Mercurial: The Definitive Guide by Bryan O'Sullivan retrieved on 2012/07/11

    RCS: Revision control software are the software tools that automate the process of Revision Control i.e. managing revisions of software artifacts.

    Revision: A revision (some seem to use it interchangeably with version while others seem to distinguish the two -- here, let us treat them as the same, for simplicity) is a state of a piece of information at a specific time that is a result of some changes to it e.g., if you modify the code and save the file, you have a new revision (or a version) of that file.

    Revision control software are also known as Version Control Software (VCS), and by a few other names.

    Revision Control Software

    In the context of RCS, what is a Revision? Give an example.

    A revision (some seem to use it interchangeably with version while others seem to distinguish the two -- here, let us treat them as the same, for simplicity) is a state of a piece of information at a specific time that is a result of some changes to it. For example, take a file containing program code. If you modify the code and save the file, you have a new revision (or a version) of that file.

    • a. Help a single user manage revisions of a single file
    • b. Help a developer recover from an incorrect modification to a code file
    • c. Make it easier for a group of developers to collaborate on a project
    • d. Manage the drift between multiple versions of your project
    • e. Detect when multiple developers make incompatible changes to the same file
    • f. All of them are benefits of RCS

    f

    Suppose you are doing a team project with Tom, Dick, and Harry, all of whom have not even heard of the term RCS. How do you explain RCS to them as briefly as possible, using the project as an example?

    W2.3b

    Project Management → Revision Control → Repositories

    Can explain repositories

    Repository (repo for short): The database of the history of a directory being tracked by an RCS software (e.g. Git).

    The repository is the database where the meta-data about the revision history are stored. Suppose you want to apply revision control on files in a directory called ProjectFoo. In that case, you need to set up a repo (short for repository) in the ProjectFoo directory, which is referred to as the working directory of the repo. For example, Git uses a hidden folder named .git inside the working directory.

    You can have multiple repos in your computer, each repo revision-controlling files of a different working directory, for examples, files of different projects.

    In the context of RCS, what is a repo?

    Guidance for the item(s) below:

    Now that we know what RCS is in general, we can try to practice it ourselves using a specific tool i.e., Git.

    The following section gives a specific scenario that includes the steps of initializing a Git repository.

    If you are new to Git, you are highly recommended to follow those steps in your own computer to get some hands-on practice as you learn Git usage.

    Note that this topic (and many other topics) come with a pre-recorded lecture video.

    Tips for watching lecture videos
    • You can watch video lectures at faster speeds (x1.25 or even x1.5) to save time.
    • Lecture videos require NUSNET login.

    W2.3c

    Tools → Git and GitHub → init: Getting started

    Video

    Can create a local Git repo

    Let's take your first few steps in your Git (with GitHub) journey.

    0. Take a peek at the full picture(?). Optionally, if you are the sort who prefers to have some sense of the full picture before you get into the nitty-gritty details, watch the video in the panel below:

    1. The first step is to install SourceTree, which is Git + a GUI for Git. If you prefer to use Git via the command line (i.e., without a GUI), you can install Git instead.

    2. Next, initialize a repository. Let us assume you want to version control content in a specific directory. In that case, you need to initialize a Git repository in that directory. Here are the steps:

    Create a directory for the repo (e.g., a directory named things).

    Windows: Click FileClone/New…. Click on Create button.
    Mac: New...Create New Repository.

    Enter the location of the directory (Windows version shown below) and click Create.

    Go to the things folder and observe how a hidden folder .git has been created.

    Windows: you might have to configure Windows Explorer to show hidden files.

    Open a Git Bash Terminal.

    If you installed SourceTree, you can click the Terminal button to open a GitBash terminal.

    Navigate to the things directory.

    Use the command git init which should initialize the repo.

    $ git init
    Initialized empty Git repository in c:/repos/things/.git/

    You can use the command ls -a to view all files, which should show the .git directory that was created by the previous command.

    $ ls -a
    . .. .git

    You can also use the git status command to check the status of the newly-created repo. It should respond with something like the following:

    git status

    # On branch master
    #
    # Initial commit
    #
    nothing to commit (create/copy files and use "git add" to track)

    Guidance for the item(s) below:

    For the next few sections, the drill is the same: first learn the high-level explanation of a revision control concept, and then follow the given scenarios yourself to learn how to apply that concept using Git.

    W2.3d

    Project Management → Revision Control → Saving history

    Can explain saving history

    Tracking and ignoring

    In a repo, you can specify which files to track and which files to ignore. Some files such as temporary log files created during the build/test process should not be revision-controlled.

    Staging and committing

    Committing saves a snapshot of the current state of the tracked files in the revision control history. Such a snapshot is also called a commit (i.e. the noun).

    When ready to commit, you first stage the specific changes you want to commit. This intermediate step allows you to commit only some changes while saving other changes for a later commit.

    W2.3e

    Tools → Git and GitHub → commit: Saving changes to history

    Video

    Can commit using Git

    After initializing a repository, Git can help you with revision controlling files inside the working directory. However, it is not automatic. It is up to you to tell Git which of your changes (aka revisions) should be committed to its memory for later use. Saving changes into Git's memory in that way is often called committing and a change saved to the revision history is called a commit.

    Working directory: the root directory revision-controlled by Git (e.g., the directory in which the repo was initialized).

    Commit (noun): a change (aka a revision) saved in the Git revision history.
    (verb): the act of creating a commit i.e., saving a change in the working directory into the Git revision history.

    Here are the steps you can follow to learn how to work with Git commits:

    1. Do some changes to the content inside the working directory e.g., create a file named fruits.txt in the things directory and add some dummy text to it.

    2. Observe how the file is detected by Git.

    The file is shown as ‘unstaged’.

    You can use the git status command to check the status of the working directory.

    git status

    # On branch master
    #
    # Initial commit
    #
    # Untracked files:
    # (use "git add <file>..." to include in what will be committed)
    #
    # a.txt
    nothing added to commit but untracked files present (use "git add" to track)

    3. Stage the changes to commit: Although Git has detected the file in the working directory, it will not do anything with the file unless you tell it to. Suppose you want to commit the current changes to the file. First, you should stage the file.

    Stage (verb): Instructing Git to prepare a file for committing.

    Select the fruits.txt and click on the Stage Selected button.

    fruits.txt should appear in the Staged files panel now.

    You can use the stage or the add command (they are synonyms, add is the more popular choice) to stage files.

    git add fruits.txt
    git status

    # On branch master
    #
    # Initial commit
    #
    # Changes to be committed:
    # (use "git rm --cached <file>..." to unstage)
    #
    # new file: fruits.txt
    #

    4. Commit the staged version of fruits.txt.

    Click the Commit button, enter a commit message e.g. add fruits.txt into the text box, and click Commit.

    Use the commit command to commit. The -m switch is used to specify the commit message.

    git commit -m "add fruits.txt"

    You can use the log command to see the commit history.

    git log

    commit 8fd30a6910efb28bb258cd01be93e481caeab846
    Author: … < … @... >
    Date: Wed Jul 5 16:06:28 2017 +0800

    Add fruits.txt

    Note the existence of something called the master branch. Git allows you to have multiple branches (i.e. it is a way to evolve the content in parallel) and Git auto-creates a branch named master on which the commits go on by default.

    5. Do a few more commits.

    1. Make some changes to fruits.txt (e.g. add some text and delete some text). Stage the changes, and commit the changes using the same steps you followed before. You should end up with something like this.

    2. Next, add two more files colors.txt and shapes.txt to the same working directory. Add a third commit to record the current state of the working directory.

    6. See the revision graph: Note how commits form a path-like structure aka the revision tree/graph. In the revision graph, each commit is shown as linked to its 'parent' commit (i.e., the commit before it).

    To see the revision graph, click on the History item on the menu on the right edge of SourceTree.

    The gitk command opens a rudimentary graphical view of the revision graph.

    • Try Git is an online simulation/tutorial of Git basics. You can try its first few steps to solidify what you have learned in this LO.

    W2.3f

    Tools → Git and GitHub → Omitting files from revision control

    Video

    Can set Git to ignore files

    Often, there are files inside the Git working folder that you don't want to revision-control e.g., temporary log files. Follow the steps below to learn how to configure Git to ignore such files.

    1. Add a file into your repo's working folder that you supposedly don't want to revision-control e.g., a file named temp.txt. Observe how Git has detected the new file.

    2. Tell Git to ignore that file:

    The file should be currently listed under Unstaged files. Right-click it and choose Ignore…. Choose Ignore exact filename(s) and click OK.

    Observe that a file named .gitignore has been created in the working directory root and has the following line in it.

    temp.txt

    Create a file named .gitignore in the working directory root and add the following line in it.

    temp.txt
    The .gitignore file

    The .gitignore file tells Git which files to ignore when tracking revision history. That file itself can be either revision controlled or ignored.

    • To version control it (the more common choice – which allows you to track how the .gitignore file changes over time), simply commit it as you would commit any other file.

    • To ignore it, follow the same steps you followed above when you set Git to ignore the temp.txt file.

    • It supports file patterns e.g., adding temp/*.tmp to the .gitignore file prevents Git from tracking any .tmp files in the temp directory.

    More information about the .gitignore file: git-scm.com/docs/gitignore

    W2.3g

    Project Management → Revision Control → Using history

    Can explain using history

    RCS tools store the history of the working directory as a series of commits. This means you should commit after each change that you want the RCS to 'remember'.

    Each commit in a repo is a recorded point in the history of the project that is uniquely identified by an auto-generated hash e.g. a16043703f28e5b3dab95915f5c5e5bf4fdc5fc1.

    You can tag a specific commit with a more easily identifiable name e.g. v1.0.2.

    To see what changed between two points of the history, you can ask the RCS tool to diff the two commits in concern.

    To restore the state of the working directory at a point in the past, you can checkout the commit in concern. i.e., you can traverse the history of the working directory simply by checking out the commits you are interested in.

    RCS: Revision control software are the software tools that automate the process of Revision Control i.e. managing revisions of software artifacts.

    W2.3h

    Tools → Git and GitHub → tag: Naming commits

    Video

    Can tag commits using Git

    Each Git commit is uniquely identified by a hash e.g., d670460b4b4aece5915caf5c68d12f560a9fe3e4. As you can imagine, using such an identifier is not very convenient for our day-to-day use. As a solution, Git allows adding a more human-readable tag to a commit e.g., v1.0-beta.

    Here's how you can tag a commit in a local repo (e.g. in the samplerepo-things repo):

    Right-click on the commit (in the graphical revision graph) you want to tag and choose Tag….

    Specify the tag name e.g. v1.0 and click Add Tag.

    The added tag will appear in the revision graph view.

    To add a tag to the current commit as v1.0,

    git tag –a v1.0

    To view tags

    git tag

    To learn how to add a tag to a past commit, go to the ‘Git Basics – Tagging’ page of the git-scm book and refer the ‘Tagging Later’ section.

    Remember to push tags to the repo. A normal push does not include tags.

    # push a specific tag
    git push origin v1.0b

    # push all tags
    git push origin --tags

    After adding a tag to a commit, you can use the tag to refer to that commit, as an alternative to using the hash.

    W2.3i

    Tools → Git and GitHub → diff: Comparing revisions

    Video

    Can compare git revisions

    Git can show you what changed in each commit.

    To see which files changed in a commit, click on the commit. To see what changed in a specific file in that commit, click on the file name.

    git show < part-of-commit-hash >

    Example:

    git show 251b4cf

    commit 5bc0e30635a754908dbdd3d2d833756cc4b52ef3
    Author: … < … >
    Date: Sat Jul 8 16:50:27 2017 +0800

    fruits.txt: replace banana with berries

    diff --git a/fruits.txt b/fruits.txt
    index 15b57f7..17f4528 100644
    --- a/fruits.txt
    +++ b/fruits.txt
    @@ -1,3 +1,3 @@
    apples
    -bananas
    +berries
    cherries

    Git can also show you the difference between two points in the history of the repo.

    Select the two points you want to compare using Ctrl+Click. The differences between the two selected versions will show up in the bottom half of SourceTree, as shown in the screenshot below.

    The same method can be used to compare the current state of the working directory (which might have uncommitted changes) to a point in the history.

    The diff command can be used to view the differences between two points of the history.

    • git diff: shows the changes (uncommitted) since the last commit.
    • git diff 0023cdd..fcd6199: shows the changes between the points indicated by commit hashes.
      Note that when using a commit hash in a Git command, you can use only the first few characters (e.g., first 7-10 chars) as that's usually enough for Git to locate the commit.
    • git diff v1.0..HEAD: shows changes that happened from the commit tagged as v1.0 to the most recent commit.

    W2.3j

    Tools → Git and GitHub → checkout: Retrieving a specific revision

    Video

    Can load a specific version of a Git repo

    Git can load a specific version of the history to the working directory. Note that if you have uncommitted changes in the working directory, you need to stash them first to prevent them from being overwritten.

    Can use Git to stash files

    You can use Git's stash feature to temporarily shelve (or stash) changes you've made to your working copy so that you can work on something else, and then come back and re-apply the stashed changes later on. -- adapted from Atlassian

    Follow this article from SourceTree creators. Note that the GUI shown in the article is slightly outdated but you should be able to map it to the current GUI.

    Follow this article from Atlassian.

    Double-click the commit you want to load to the working directory, or right-click on that commit and choose Checkout....

    Click OK to the warning about ‘detached HEAD’ (similar to below).

    The specified version is now loaded to the working folder, as indicated by the HEAD label. HEAD is a reference to the currently checked out commit.

    If you checkout a commit that comes before the commit in which you added the .gitignore file, Git will now show ignored files as ‘unstaged modifications’ because at that stage Git hasn’t been told to ignore those files.

    To go back to the latest commit, double-click it.

    Use the checkout <commit-identifier> command to change the working directory to the state it was in at a specific past commit.

    • git checkout v1.0: loads the state as at commit tagged v1.0
    • git checkout 0023cdd: loads the state as at commit with the hash 0023cdd
    • git checkout HEAD~2: loads the state that is 2 commits behind the most recent commit

    For now, you can ignore the warning about ‘detached HEAD’.

    W2.3k : OPTIONAL

    Tools → Git and GitHub → stash: Shelving changes temporarily

    Video

    Can use Git to stash files

    You can use Git's stash feature to temporarily shelve (or stash) changes you've made to your working copy so that you can work on something else, and then come back and re-apply the stashed changes later on. -- adapted from Atlassian

    Follow this article from SourceTree creators. Note that the GUI shown in the article is slightly outdated but you should be able to map it to the current GUI.

    Follow this article from Atlassian.

    Guidance for the item(s) below:

    Having learned how to use Git in your own computer, let's also learn a bit about working with remote code repositories too. Yes it's a bit too much to take in one week but we want you to start using Git in your iP from the very beginning.

    [W2.4] RCS: Remote Repos

    W2.4a

    Project Management → Revision Control → Remote repositories

    Video

    Can explain remote repositories

    Remote repositories are repos that are hosted on remote computers and allow remote access. They are especially useful for sharing the revision history of a codebase among team members of a multi-person project. They can also serve as a remote backup of your codebase.

    It is possible to set up your own remote repo on a server, but the easier option is to use a remote repo hosting service such as GitHub or BitBucket.

    You can clone a repo to create a copy of that repo in another location on your computer. The copy will even have the revision history of the original repo i.e., identical to the original repo. For example, you can clone a remote repo onto your computer to create a local copy of the remote repo.

    When you clone from a repo, the original repo is commonly referred to as the upstream repo. A repo can have multiple upstream repos. For example, let's say a repo repo1 was cloned as repo2 which was then cloned as repo3. In this case, repo1 and repo2 are upstream repos of repo3.

    You can pull from one repo to another, to receive new commits in the second repo, if the repos have a shared history. Let's say some new commits were added to the upstream repo is a term used to refer to the repo you cloned fromupstream repo after you cloned it and you would like to copy over those new commits to your own clone i.e., sync your clone with the upstream repo. In that case, you pull from the upstream repo to your clone.

    You can push new commits in one repo to another repo which will copy the new commits onto the destination repo. Note that pushing to a repo requires you to have write-access to it. Furthermore, you can push between repos only if those repos have a shared history among them (i.e., one was created by copying the other at some point in the past).

    Cloning, pushing, and pulling can be done between two local repos too, although it is more common for them to involve a remote repo.

    A repo can work with any number of other repositories as long as they have a shared history e.g., repo1 can pull from (or push to) repo2 and repo3 if they have a shared history between them.

    A fork is a remote copy of a remote repo. As you know, cloning creates a local copy of a repo. In contrast, forking creates a remote copy of a Git repo hosted on GitHub. This is particularly useful if you want to play around with a GitHub repo but you don't have write permissions to it; you can simply fork the repo and do whatever you want with the fork as you are the owner of the fork.

    A pull request (PR for short) is a mechanism for contributing code to a remote repo, i.e., "I'm requesting you to pull my proposed changes to your repo". For this to work, the two repos must have a shared history. The most common case is sending PRs from a fork to its upstream repo is a repo you forked fromupstream repo.

    Here is a scenario that includes all the concepts introduced above (click inside the slide to advance the animation):

    W2.4b

    Tools → Git and GitHub → clone: Copying a repo

    Video

    Can clone a remote repo

    Given below is an example scenario you can try yourself to learn Git cloning.

    You can clone a repo to create a copy of that repo in another location on your computer. The copy will even have the revision history of the original repo i.e., identical to the original repo. For example, you can clone a remote repo onto your computer to create a local copy of the remote repo.

    Suppose you want to clone the sample repo samplerepo-things to your computer.

    Note that the URL of the GitHub project is different from the URL you need to clone a repo in that GitHub project. e.g.

    GitHub project URL: https://github.com/se-edu/samplerepo-things
    Git repo URL: https://github.com/se-edu/samplerepo-things.git (note the .git at the end)

    FileClone / New… and provide the URL of the repo and the destination directory.

    You can use the clone command to clone a repo.

    Follow the instructions given here.

    W2.4c

    Tools → Git and GitHub → pull, fetch: Downloading data from other repos

    Video

    Can pull changes from a repo

    Here's a scenario you can try in order to learn how to pull commits from another repo to yours.

    You can pull from one repo to another, to receive new commits in the second repo, if the repos have a shared history. Let's say some new commits were added to the upstream repo is a term used to refer to the repo you cloned fromupstream repo after you cloned it and you would like to copy over those new commits to your own clone i.e., sync your clone with the upstream repo. In that case, you pull from the upstream repo to your clone.

    1. Clone a repo (e.g., the repo used in [Git & GitHub → Clone]) to be used for this activity.

    2. Delete the last few commits to simulate cloning the repo a few commits ago.

    clone: Copying a repo

    Can clone a remote repo

    Given below is an example scenario you can try yourself to learn Git cloning.

    You can clone a repo to create a copy of that repo in another location on your computer. The copy will even have the revision history of the original repo i.e., identical to the original repo. For example, you can clone a remote repo onto your computer to create a local copy of the remote repo.

    Suppose you want to clone the sample repo samplerepo-things to your computer.

    Note that the URL of the GitHub project is different from the URL you need to clone a repo in that GitHub project. e.g.

    GitHub project URL: https://github.com/se-edu/samplerepo-things
    Git repo URL: https://github.com/se-edu/samplerepo-things.git (note the .git at the end)

    FileClone / New… and provide the URL of the repo and the destination directory.

    You can use the clone command to clone a repo.

    Follow the instructions given here.

    Right-click the target commit (i.e. the commit that is 2 commits behind the tip) and choose Reset current branch to this commit.

    Choose the Hard - … option and click OK.

    This is what you will see.

    Note the following (cross refer the screenshot above):

    Arrow marked as a: The local repo is now at this commit, marked by the master label.
    Arrow marked as b: The origin/master label shows what is the latest commit in the master branch in the remote repo.

    Use the reset command to delete commits at the tip of the revision history.

    git reset --hard HEAD~2

    Now, your local repo state is exactly how it would be if you had cloned the repo 2 commits ago, as if somebody has added two more commits to the remote repo since you cloned it.

    3. Pull from the other repo: To get those missing commits to your local repo (i.e. to sync your local repo with upstream repo) you can do a pull.

    Click the Pull button in the main menu, choose origin and master in the next dialog, and click OK.

    Now you should see something like this where master and origin/master are both pointing the same commit.

    git pull origin

    You can also do a fetch instead of a pull in which case the new commits will be downloaded to your repo but the working directory will remain at the current commit. To move the current state to the latest commit that was downloaded, you need to do a merge. A pull is a shortcut that does both those steps in one go.

    Working with multiple remotes

    When you clone a repo, Git automatically adds a remote repo named origin to your repo configuration. As you know, you can pull commits from that repo. As you know, a Git repo can work with remote repos other than the one it was cloned from.

    A repo can work with any number of other repositories as long as they have a shared history e.g., repo1 can pull from (or push to) repo2 and repo3 if they have a shared history between them.

    To communicate with another remote repo, you can first add it as a remote of your repo. Here is an example scenario you can follow to learn how to pull from another repo:

    1. Open the local repo in SourceTree. Suggested: Use your local clone of the samplerepo-things repo.

    2. Choose RepositoryRepository Settings menu option.

    3. Add a new remote to the repo with the following values.

      • Remote name: the name you want to assign to the remote repo e.g., upstream1
      • URL/path: the URL of your repo (ending in .git) that. Suggested: https://github.com/se-edu/samplerepo-things-2.git (samplerepo-things-2 is another repo that has a shared history with samplerepo-things)
      • Username: your GitHub username

    4. Now, you can pull from the added repo as you did before but choose the remote name of the repo you want to pull from (instead of origin):

      If the Remote branch to pull dropdown is empty, click the Refresh button on its right.

    5. If the pull from the samplerepo-things-2 was successful, you should have received one more commit into your local repo.

    1. Navigate to the folder containing the local repo.

    2. Set the new remote repo as a remote of the local repo.
      command: git remote add {remote_name} {remote_repo_url}
      e.g., git remote add upstream1 https://github.com/johndoe/foobar.git

    3. Now you can pull from the new remote.
      e.g., git pull upstream1 master

    W2.4d

    Tools → Git and GitHub → Fork: Creating a remote copy

    Video

    Can fork a repo

    Given below is a scenario you can try in order to learn how to fork a repo:.

    A fork is a remote copy of a remote repo. As you know, cloning creates a local copy of a repo. In contrast, forking creates a remote copy of a Git repo hosted on GitHub. This is particularly useful if you want to play around with a GitHub repo but you don't have write permissions to it; you can simply fork the repo and do whatever you want with the fork as you are the owner of the fork.

    0. Create a GitHub account if you don't have one yet.

    1. Go to the GitHub repo you want to fork e.g., samplerepo-things

    2. Click on the button on the top-right corner. In the next step, choose to fork to your own account or to another GitHub organization that you are an admin of.

    GitHub does not allow you to fork the same repo more than once to the same destination. If you want to re-fork, you need to delete the previous fork.

    W2.4e

    Tools → Git and GitHub → push: Uploading data to other repos

    Video

    Can push to a remote repo

    Given below is a scenario you can try in order to learn how to push commits to a remote repo hosted on GitHub:

    You can push new commits in one repo to another repo which will copy the new commits onto the destination repo. Note that pushing to a repo requires you to have write-access to it. Furthermore, you can push between repos only if those repos have a shared history among them (i.e., one was created by copying the other at some point in the past).

    1. Fork an existing GitHub repo (e.g., samplerepo-things) to your GitHub account.

    2. Clone the fork (not the original) to your computer.

    3. Commit some changes in your local repo.

    4. Push the new commits to your fork on GitHub

    Click the Push button on the main menu, ensure the settings are as follows in the next dialog, and click the Push button on the dialog.

    Tags are not included in a normal push. Remember to tick Push all tags when pushing to the remote repo if you want them to be pushed to the repo.

    Use the command git push origin master. Enter your Github username and password when prompted.

    Tags are not included in a normal push. To push a tag, use this command: git push origin <tag_name> e.g. git push origin v1.0

    You can push to repos other than the one you cloned from, as long as the target repo and your repo have a shared history.

    1. Add the GitHub repo URL as a remote, if you haven't done so already.
    2. Push to the target repo.
    Working with multiple remotes

    When you clone a repo, Git automatically adds a remote repo named origin to your repo configuration. As you know, you can pull commits from that repo. As you know, a Git repo can work with remote repos other than the one it was cloned from.

    A repo can work with any number of other repositories as long as they have a shared history e.g., repo1 can pull from (or push to) repo2 and repo3 if they have a shared history between them.

    To communicate with another remote repo, you can first add it as a remote of your repo. Here is an example scenario you can follow to learn how to pull from another repo:

    1. Open the local repo in SourceTree. Suggested: Use your local clone of the samplerepo-things repo.

    2. Choose RepositoryRepository Settings menu option.

    3. Add a new remote to the repo with the following values.

      • Remote name: the name you want to assign to the remote repo e.g., upstream1
      • URL/path: the URL of your repo (ending in .git) that. Suggested: https://github.com/se-edu/samplerepo-things-2.git (samplerepo-things-2 is another repo that has a shared history with samplerepo-things)
      • Username: your GitHub username

    4. Now, you can pull from the added repo as you did before but choose the remote name of the repo you want to pull from (instead of origin):

      If the Remote branch to pull dropdown is empty, click the Refresh button on its right.

    5. If the pull from the samplerepo-things-2 was successful, you should have received one more commit into your local repo.

    1. Navigate to the folder containing the local repo.

    2. Set the new remote repo as a remote of the local repo.
      command: git remote add {remote_name} {remote_repo_url}
      e.g., git remote add upstream1 https://github.com/johndoe/foobar.git

    3. Now you can pull from the new remote.
      e.g., git pull upstream1 master

    Push your repo to the new remote the usual way, but select the name of target remote instead of origin and remember to select the Track checkbox.

    Push to the new remote the usual way e.g., git push upstream1 master (assuming you gave the name upstream1 to the remote).

    You can even push an entire local repository to GitHub, to form an entirely new remote repository. For example, you created a local repo and worked with it for a while but now you want to upload it onto GitHub (as a backup or to share it with others). The steps are given below.

    1. Create an empty remote repo on GitHub.

    1. Login to your GitHub account and choose to create a new Repo.

    2. In the next screen, provide a name for your repo but keep the Initialize this repo ... tick box unchecked.

    3. Note the URL of the repo. It will be of the form https://github.com/{your_user_name}/{repo_name}.git.
      e.g., https://github.com/johndoe/foobar.git (note the .git at the end)

    2. Add the GitHub repo URL as a remote of the local repo. You can give it the name origin (or any other name).

    Working with multiple remotes

    When you clone a repo, Git automatically adds a remote repo named origin to your repo configuration. As you know, you can pull commits from that repo. As you know, a Git repo can work with remote repos other than the one it was cloned from.

    A repo can work with any number of other repositories as long as they have a shared history e.g., repo1 can pull from (or push to) repo2 and repo3 if they have a shared history between them.

    To communicate with another remote repo, you can first add it as a remote of your repo. Here is an example scenario you can follow to learn how to pull from another repo:

    1. Open the local repo in SourceTree. Suggested: Use your local clone of the samplerepo-things repo.

    2. Choose RepositoryRepository Settings menu option.

    3. Add a new remote to the repo with the following values.

      • Remote name: the name you want to assign to the remote repo e.g., upstream1
      • URL/path: the URL of your repo (ending in .git) that. Suggested: https://github.com/se-edu/samplerepo-things-2.git (samplerepo-things-2 is another repo that has a shared history with samplerepo-things)
      • Username: your GitHub username

    4. Now, you can pull from the added repo as you did before but choose the remote name of the repo you want to pull from (instead of origin):

      If the Remote branch to pull dropdown is empty, click the Refresh button on its right.

    5. If the pull from the samplerepo-things-2 was successful, you should have received one more commit into your local repo.

    1. Navigate to the folder containing the local repo.

    2. Set the new remote repo as a remote of the local repo.
      command: git remote add {remote_name} {remote_repo_url}
      e.g., git remote add upstream1 https://github.com/johndoe/foobar.git

    3. Now you can pull from the new remote.
      e.g., git pull upstream1 master

    3. Push the repo to the remote.

    Push each branch to the new remote the usual way but use the -u flag to inform Git that you wish to i.e., remember which branch in the remote repo corresponds to which branch in the local repotrack the branch.
    e.g., git push -u origin master

    Guidance for the item(s) below:

    As you are likely to be using an IDE for the iP, let's learn at least enough about IDEs to get you started using one.

    🤔 In case you are puzzled by the sudden change of topic, it's because we take an iterative approach to covering topics, as explained in the panel below:

    What does mean to 'follow an iterative approach in covering topics'?

    It means, we cover a little bit of i.e., requirements, design, testing, project management, ...all SE aspects at first and then iteratively go deeper into them later, revisiting each aspect many time over the course of the semester. In contrast, a sequential approach would have covered one SE aspect before moving to the next (e.g., teach the requirements aspect completely before moving to the design aspect).

    The choice of which topics are covered each week is driven by the project i.e., we give priority to topics that you'll need to apply soon in the project that you will be doing in parallel.

    This way of 'jumping around' topics feels chaotic but consider the benefits:

    • It allows you to start doing SE projects early, and iteratively too. That is, you can start with a small project from the very start and make it bigger progressively, learning from earlier mistakes, and getting multiple chances improve on previous attempts.
    • Important SE aspects such as testing can be practiced from the very beginning. If we followed a sequential approach, you an only learn it near the end of the semester.
    • Lower risk of missing out some SE aspects altogether. For example, suppose your schedule got heavier in the second half of the semester and you could barely follow the module during that half. You still go away with the basic knowledge of all SE aspects rather than knowing some aspects fully and missing some other aspects altogether.

    To help you cope with the non-sequential progression of topics, this module website contains two versions of the topics. In the Schedule page, you'll find the topics organized into the order we cover them in each week. In the Textbook page, you'll find the topics in their natural sequential order. This format is suitable for exam reference.

    [W2.5] IDEs: Basic Features

    W2.5a

    Implementation → IDEs → What

    Can explain IDEs

    Professional software engineers often write code using Integrated Development Environments (IDEs). IDEs support most development-related work within the same tool (hence, the term integrated).

    An IDE generally consists of:

    • A source code editor that includes features such as syntax coloring, auto-completion, easy code navigation, error highlighting, and code-snippet generation.
    • A compiler and/or an interpreter (together with other build automation support) that facilitates the compilation/linking/running/deployment of a program.
    • A debugger that allows the developer to execute the program one step at a time to observe the run-time behavior in order to locate bugs.
    • Other tools that aid various aspects of coding e.g. support for automated testing, drag-and-drop construction of UI components, version management support, simulation of the target runtime platform, and modeling support.

    Examples of popular IDEs:

    • Java: Eclipse, Intellij IDEA, NetBeans
    • C#, C++: Visual Studio
    • Swift: XCode
    • Python: PyCharm

    Some web-based IDEs have appeared in recent times too e.g., Amazon's Cloud9 IDE.

    Some experienced developers, in particular those with a UNIX background, prefer lightweight yet powerful text editors with scripting capabilities (e.g. Emacs) over heavier IDEs.

    • a. Compiling
    • b. Syntax error highlighting
    • c. Debugging
    • d. Code navigation e.g., to navigate from a method call to the method implementation
    • e. Simulation e.g., run a mobile app in a simulator
    • f. Code analysis e.g. to find unreachable code
    • g. Reverse engineering design/documentation e.g. generate diagrams from code
    • h. Visual programming e.g. write programs using ‘drag and drop’ actions instead of typing code
    • i. Syntax assistance e.g., show hints as you type
    • j. Code generation e.g., to generate the code required by simply specifying which component/structure you want to implement
    • k. Extension i.e., ability to add more functionality to the IDE using plugins

    All.

    Explanation: While all of these features may not be present in some IDEs, most do have these features in some form or other.

    W2.5b

    Tools → IntelliJ IDEA → Project setup

    Can setup a project in an IDE

    Running IntelliJ IDEA for the First Time

    A slightly more detailed explanation (from CodeLaunch) with some additional info at the end.


    Guidance for the item(s) below:

    As you start adding features to your project iteratively, you'll need a way to detect if the new code breaks the existing code. Next, let's learn a rather simple way to do that using a certain type of testing (we'll be learning more sophisticated methods in later weeks).

    This also means we are not switching focus from the implementation aspect to the testing aspect of SE.

    [W2.6] Automated Testing of Text UIs

    W2.6a

    Quality Assurance → Testing → Introduction → What

    Video

    Can explain testing

    Testing: Operating a system or component under specified conditions, observing or recording the results, and making an evaluation of some aspect of the system or component. –- source: IEEE

    When testing, you execute a set of test cases. A test case specifies how to perform a test. At a minimum, it specifies the input to the software under test (SUT) and the expected behavior.

    Example: A minimal test case for testing a browser:

    • Input – Start the browser using a blank page (vertical scrollbar disabled). Then, load longfile.html located in the test data folder.
    • Expected behavior – The scrollbar should be automatically enabled upon loading longfile.html.

    Test cases can be determined based on the specification, reviewing similar existing systems, or comparing to the past behavior of the SUT.

    Other details a test case can contain extra A more elaborate test case can have other details such as those given below.
    • A unique identifier : e.g. TC0034-a
    • A descriptive name: e.g. vertical scrollbar activation for long web pages
    • Objectives: e.g. to check whether the vertical scrollbar is correctly activated when a long web page is loaded to the browser
    • Classification information: e.g. priority - medium, category - UI features
    • Cleanup, if any: e.g. empty the browser cache.

    For each test case you should do the following:

    1. Feed the input to the SUT
    2. Observe the actual output
    3. Compare actual output with the expected output

    A test case failure is a mismatch between the expected behavior and the actual behavior. A failure indicates a potential defect (or a bug), unless the error is in the test case itself.

    Example: In the browser example above, a test case failure is implied if the scrollbar remains disabled after loading longfile.html. The defect/bug causing that failure could be an uninitialized variable.

    A deeper look at the definition of testing extra

    Here is another definition of testing:

    Software testing consists of the dynamic verification that a program provides expected behaviors on a finite set of test cases, suitably selected from the usually infinite execution domain. -– source: Software Engineering Book of Knowledge V3

    Some things to note (indicated by keywords in the above definition):

    • Dynamic: Testing involves executing the software. It is not by examining the code statically.
    • Finite: In most non-trivial cases there are potentially infinite test scenarios but resource constraints dictate that we can test only a finite number of scenarios.
    • Selected: In most cases it is not possible to test all scenarios. That means we need to select what scenarios to test.
    • Expected: Testing requires some knowledge of how the software is expected to behave.

    Explain how the concepts of testing, test cases, test failure, and defects are related to each other.

    W2.6b

    Quality Assurance → Testing → Regression Testing → What

    Video

    Can explain regression testing

    When you modify a system, the modification may result in some unintended and undesirable effects on the system. Such an effect is called a regression.

    Regression testing is the re-testing of the software to detect regressions. Note that to detect regressions, you need to retest all related components, even if they had been tested before.

    Regression testing is more effective when it is done frequently, after each small change. However, doing so can be prohibitively expensive if testing is done manually. Hence, regression testing is more practical when it is automated.

    Regression testing is the automated re-testing of a software after it has been modified.

    c.

    Explanation: Regression testing need not be automated but automation is highly recommended.

    Explain why and when you would do regression testing in a software project.

    W2.6c

    Quality Assurance → Testing → Test Automation → What

    Can explain test automation

    An automated test case can be run programmatically and the result of the test case (pass or fail) is determined programmatically. Compared to manual testing, automated testing reduces the effort required to run tests repeatedly and increases precision of testing (because manual testing is susceptible to human errors).

    W2.6d

    Quality Assurance → Testing → Test Automation → Automated testing of CLI applications

    Video

    Can semi-automate testing of CLIs

    A simple way to semi-automate testing of a CLI (Command Line Interface) app is by using input/output re-direction.

    • First, you feed the app with a sequence of test inputs that is stored in a file while redirecting the output to another file.
    • Next, you compare the actual output file with another file containing the expected output.

    Let's assume you are testing a CLI app called AddressBook. Here are the detailed steps:

    1. Store the test input in the text file input.txt.

      add Valid Name p/12345 valid@email.butNoPrefix
      add Valid Name 12345 e/valid@email.butPhonePrefixMissing
    2. Store the output you expect from the SUT in another text file expected.txt.

      Command: || [add Valid Name p/12345 valid@email.butNoPrefix]
      Invalid command format: add

      Command: || [add Valid Name 12345 e/valid@email.butPhonePrefixMissing]
      Invalid command format: add
    3. Run the program as given below, which will redirect the text in input.txt as the input to AddressBook and similarly, will redirect the output of AddressBook to a text file output.txt. Note that this does not require any code changes to AddressBook.

      java AddressBook < input.txt > output.txt
      • The way to run a CLI program differs based on the language.
        e.g., In Python, assuming the code is in AddressBook.py file, use the command
        python AddressBook.py < input.txt > output.txt

      • If you are using Windows, use a normal command window to run the app, not a PowerShell window.

      More on the > operator and the < operator extra

      A CLI program takes input from the keyboard and outputs to the console. That is because those two are the default input and output streams, respectively. But you can change that behavior using < and > operators. For example, if you run AddressBook in a command window, the output will be shown in the console, but if you run it like this,

      java AddressBook > output.txt 

      the Operating System then creates a file output.txt and stores the output in that file instead of displaying it in the console. No file I/O coding is required. Similarly, adding < input.txt (or any other filename) makes the OS redirect the contents of the file as input to the program, as if the user typed the content of the file one line at a time.

      Resources:

    4. Next, you compare output.txt with the expected.txt. This can be done using a utility such as Windows' FC (i.e. File Compare) command, Unix's diff command, or a GUI tool such as WinMerge.

      FC output.txt expected.txt

    Note that the above technique is only suitable when testing CLI apps, and only if the exact output can be predetermined. If the output varies from one run to the other (e.g. it contains a time stamp), this technique will not work. In those cases, you need more sophisticated ways of automating tests.

    CLI application: An application that has a Command Line Interface. i.e. user interacts with the app by typing in commands.

    Follow up notes for the item(s) above:

    Congrats! You've made it to the end of this week's topics. It feels like a lot right now but now that we got an early start, this stuff will be second nature to you by the time you are done with the semester. 😃