- 原地址:Survey: Automatically Generated Test Suites for JavaScript
You are being invited to participate in a research study that explores the effort developers put into understanding the content of the automatically generated test suite.
The purpose of this research study is to explore if different kinds of automatically generated test suites affect developers’ performance on program comprehension tasks. This study will take you approximately 30 minutes to complete. The anonymised data will be used for a master’s thesis project. We will be asking you to read multiple test suites, and answer related questions.
As with any online activity, the risk of a breach is always possible. To the best of our ability, your answers in this study will remain confidential. We will minimize any risks.
Your participation in this study is entirely voluntary and you can withdraw at any time. The email address data will be immediately deleted after the project ends, and the anonymous survey responses will be uploaded to 4TU.ResearchData with public access.
If you have any questions, please contact [email protected]. If you agree to this opening statement, you could participate in this study by clicking the button below and moving to the next page. Remember, your participation is completely voluntary, and you’re free to withdraw from the study at any time.
Thank you for considering participating in this research study.
Next
Space Cell | < 1 year | 1-2 years | 3-6 years | 6-10 years | > 10 years |
---|---|---|---|---|---|
Software testing | Software testing: < 1 year | Software testing: 1-2 years | Software testing: 3-6 years | Software testing: 6-10 years | Software testing: > 10 years |
JavaScript | JavaScript: < 1 year | JavaScript: 1-2 years | JavaScript: 3-6 years | JavaScript: 6-10 years | JavaScript: > 10 years |
Designers created these tests to check the behavior of the system’s part you’ve just modified. You changed this behavior intentionally to implement the new feature, so you know that the source code isn’t the issue. The problem is with the test suite—it hasn’t been updated to reflect the new expected behavior of the system.
We value your participation in this study and hope to gather the most accurate data possible to enhance the quality of our research. As part of this survey, we are recording the time you spend on each task.
We kindly request that once you start a task, you continue working on it without interruption until it’s completed. This measure will ensure the timing data we collect reflects the time actively spent on the task.
Please understand, this is not a test of speed, but a means for us to better understand the time dynamics of the tasks involved in our study.
We appreciate your understanding and cooperation. Thank you for your time and effort.
As described in the previous page’s introduction, the bugs in this test code are caused by changes in the internal logic of certain methods in the class under test. The following image is a screenshot of the change history of the class under test. You can find the changes history here. These code changes resulted in the failure of some test cases in the test suite.
Your task is to find bugs in the test suite and answer questions.
You can find the class under test here.
/**
* Class representing a Polygon.
*/
export default class Polygon {
/**
* Create a polygon.
*/
constructor() {
this.vertices = [];
}
/**
* Add a vertex to the polygon.
* @param {Object} vertex - The vertex to add.
* @throws {Error} If the vertex is not an object with numeric x and y properties.
*/
addVertex(vertex) {
if (typeof vertex.x !== "number" || typeof vertex.y !== "number") {
throw new Error(
"Vertex must be an object with numeric x and y properties"
);
}
this.vertices.push(vertex);
}
/**
* Remove a vertex from the polygon by its index.
* @param {number} index - The index of the vertex to remove.
* @throws {Error} If the index is out of bounds.
*/
removeVertex(index) {
if (index < 0 || index >= this.vertices.length) {
throw new Error("Index out of bounds");
}
this.vertices.splice(index, 1);
}
/**
* Calculate the perimeter of the polygon.
* @returns {number} The calculated perimeter.
*/
calculatePerimeter() {
let perimeter = 0;
for (let i = 0; i < this.vertices.length; i++) {
const v1 = this.vertices[i];
const v2 = this.vertices[(i + 1) % this.vertices.length];
const dx = v2.x - v1.x;
const dy = v2.y - v1.y;
perimeter += Math.sqrt(dx * dx + dy * dy);
}
return perimeter;
}
/**
* Calculate the area of the polygon.
* @returns {number} The calculated area.
*/
calculateArea() {
let area = 0;
for (let i = 0; i < this.vertices.length; i++) {
const v1 = this.vertices[i];
const v2 = this.vertices[(i + 1) % this.vertices.length];
area += v1.x * v2.y - v2.x * v1.y;
}
return Math.abs(area) / 2;
}
/**
* Check if a point is inside the polygon.
* @param {Object} point - The point to check.
* @returns {boolean} True if the point is inside the polygon, false otherwise.
*/
isPointInside(point) {
// This is a simple implementation based on ray casting algorithm and it assumes that the polygon is simple and convex
let inside = false;
for (
let i = 0, j = this.vertices.length - 1;
i < this.vertices.length;
j = i++
) {
const xi = this.vertices[i].x,
yi = this.vertices[i].y;
const xj = this.vertices[j].x,
yj = this.vertices[j].y;
const intersect =
yi > point.y !== yj > point.y &&
point.x < ((xj - xi) * (point.y - yi)) / (yj - yi) + xi;
if (intersect) inside = !inside;
}
return inside;
}
/**
* Translate the polygon by a vector.
* @param {Object} vector - The vector to translate the polygon.
* @throws {Error} If the vector is not an object with numeric x and y properties.
*/
translate(vector) {
if (typeof vector.x !== "number" || typeof vector.y !== "number") {
throw new Error(
"Vector must be an object with numeric x and y properties"
);
}
for (let vertex of this.vertices) {
vertex.x += vector.x;
vertex.y += vector.y;
}
}
/**
* Scale the polygon by a factor.
* @param {number} factor - The scale factor.
* @throws {Error} If the scale factor is not a number.
*/
scale(factor) {
if (typeof factor !== "number") {
throw new Error("Scale factor must be a number");
}
for (let vertex of this.vertices) {
vertex.x *= factor;
vertex.y *= factor;
}
}
/**
* Rotate the polygon by an angle.
* @param {number} angle - The rotation angle.
* @throws {Error} If the rotation angle is not a number.
*/
rotate(angle) {
if (typeof angle !== "number") {
throw new Error("Rotation angle must be a number");
}
const cos = Math.cos(angle);
const sin = Math.sin(angle);
for (let vertex of this.vertices) {
const x = vertex.x * cos - vertex.y * sin;
const y = vertex.x * sin + vertex.y * cos;
vertex.x = x;
vertex.y = y;
}
}
}
import Polygon from "Polygon.js";
import chai from "chai";
import chaiAsPromised from "chai-as-promised";
chai.use(chaiAsPromised);
const expect = chai.expect;
describe("Polygon.js", () => {
context("Tests for multiple actions return Polygon object", () => {
it("calls rotate after addVertex and returns Polygon object", async () => {
const polygon = new Polygon();
const vertex = {
x: 128,
y: -7,
};
await polygon.addVertex(vertex);
const angle = 39;
await polygon.rotate(angle);
expect(JSON.parse(JSON.stringify(polygon))).to.deep.equal({
vertices: [
{
x: 40.876863046060585,
y: 121.49930891784368,
},
],
});
});
it("calls scale after addVertex and returns Polygon object", async () => {
const polygon = new Polygon();
const vertex = {
x: 113,
y: -704,
};
await polygon.addVertex(vertex);
const factor = 15;
await polygon.scale(factor);
expect(JSON.parse(JSON.stringify(polygon))).to.deep.equal({
vertices: [
{
x: 1695,
y: -10560,
},
],
});
});
it("calls rotate and returns Polygon object", async () => {
const polygon = new Polygon();
const vertex = {
x: -82,
y: -356,
};
await polygon.addVertex(vertex);
const angle = "tqp1-E";
await polygon.rotate(angle);
expect(JSON.parse(JSON.stringify(polygon))).to.deep.equal({
vertices: [
{
x: null,
y: null,
},
],
});
});
});
context("Tests for error handling of addVertex and removeVertex", () => {
it("throws an error with positive index", async () => {
const polygon = new Polygon();
const index = 254;
try {
await polygon.removeVertex(index);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("throws an error with array vertex.x ", async () => {
const polygon = new Polygon();
const vertex = {
x: ["Ln0qFysBnz1"],
y: "RTurhxUamchFWW",
};
try {
await polygon.addVertex(vertex);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("calls removeVertex after addVertex and returns Polygon object", async () => {
const polygon = new Polygon();
const vertex = {
y: -9.058398620535518,
x: -2.4308041085729872,
};
await polygon.addVertex(vertex);
const index = 0;
await polygon.removeVertex(index);
expect(JSON.parse(JSON.stringify(polygon))).to.deep.equal({
vertices: [],
});
});
it("throws an error with string factor", async () => {
const polygon = new Polygon();
const vertex = {
x: 282,
y: -46,
};
await polygon.addVertex(vertex);
const factor = "Nn_ESQK";
try {
await polygon.scale(factor);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("throws an error with undefined vertex", async () => {
const polygon = new Polygon();
const vertex = undefined;
try {
await polygon.addVertex(vertex);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("throws an error with null vertex", async () => {
const polygon = new Polygon();
const vertex = null;
try {
await polygon.addVertex(vertex);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("throws an error with undefined point.y", async () => {
const polygon = new Polygon();
const vertex = {
x: 212,
y: -72,
};
await polygon.addVertex(vertex);
const point = undefined;
try {
await polygon.isPointInside(point);
} catch (e) {
expect(e).to.be.an("error");
}
});
});
context("Test for isPointInside", () => {
it("calls isPointInside and returns false", async () => {
const polygon = new Polygon();
const point = {
y: 90,
x: 198,
};
const returnValue = await polygon.isPointInside(point);
expect(returnValue).to.equal(false);
});
});
context("Tests for translate with different arguments", () => {
it("calls translate after addVertex and returns Polygon object", async () => {
const polygon = new Polygon();
const vertex = {
x: -94,
y: 82,
};
await polygon.addVertex(vertex);
const vector = {
x: 108,
y: -168,
};
await polygon.translate(vector);
expect(JSON.parse(JSON.stringify(polygon))).to.deep.equal({
vertices: [
{
x: -202,
y: 250,
},
],
});
});
it("throws an error with string vector.x", async () => {
const polygon = new Polygon();
const vector = {
x: "zwxHQ",
y: 916,
};
try {
await polygon.translate(vector);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("calls translate and returns Polygon object", async () => {
const polygon = new Polygon();
const vector = {
x: -287,
y: -47,
};
await polygon.translate(vector);
expect(JSON.parse(JSON.stringify(polygon))).to.deep.equal({
vertices: [],
});
});
});
context("Test for calculatePerimeter", () => {
it("calls calculatePerimeter after addVertex and returns positive", async () => {
const polygon = new Polygon();
const vertex1 = {
x: 125,
y: -7,
};
await polygon.addVertex(vertex1);
const returnValue = await polygon.calculatePerimeter();
expect(returnValue).to.equal(0);
});
});
context("Tests for calculateArea", () => {
it("throws an error with vertices.length=2", async () => {
const polygon = new Polygon();
const vector1 = {
x: 459,
y: -387,
};
await polygon.addVertex(vector1);
const vector2 = {
x: 361,
y: 23,
};
await polygon.addVertex(vector2);
try {
const returnValue = await polygon.calculateArea();
expect.fail();
} catch (e) {
expect(e).to.be.an("error");
}
});
it("throws an error with vertices.length=1", async () => {
const polygon = new Polygon();
const vertex1 = {
x: 23,
y: 499,
};
await polygon.addVertex(vertex1);
try {
const returnValue = await polygon.calculateArea();
expect.fail();
} catch (e) {
expect(e).to.be.an("error");
}
});
});
});
test case name what the bug is
Bug1
Bug2
Bug3
Bug4
Bug5
Space Cell | test case name | what the bug is |
---|---|---|
Bug1 | Bug1: test case name | Bug1: what the bug is |
Bug2 | Bug2: test case name | Bug2: what the bug is |
Bug3 | Bug3: test case name | Bug3: what the bug is |
Bug4 | Bug4: test case name | Bug4: what the bug is |
Bug5 | Bug5: test case name | Bug5: what the bug is |
Suppose you are a new developer who is dealing with legacy codebase, one of the main challenges you face is understanding the existing system, which can be complex and convoluted. To make matters worse, the original developers are no longer available to address queries, and the documentation provided is both poor and outdated.
Despite these obstacles, there is a silver lining: the system boasts a suite of automatically generated unit tests for the class you are currently investigating. Remarkably, all the test cases in the suite have passed successfully.
Recognizing the value of these automatically generated unit tests, your objective is to dive into the content of this test suite. Your aim is to extract meaningful insights regarding the intended behavior and expected functionality of the CUT (class under test). By analyzing the test suite, you hope to gain a clearer understanding of how the CUT is supposed to do and what the expected outcome is under various circumstances.
We value your participation in this study and hope to gather the most accurate data possible to enhance the quality of our research. As part of this survey, we are recording the time you spend on each task.
We kindly request that once you start a task, you continue working on it without interruption until it’s completed. This measure will ensure the timing data we collect reflects the time actively spent on the task.
Please understand, this is not a test of speed, but a means for us to better understand the time dynamics of the tasks involved in our study.
We appreciate your understanding and cooperation. Thank you for your time and effort.
Task: Executable Documentation
In this task, you will first be asked to carefully read a test suite that we have prepared.
This test suite contains valuable information necessary to answer the subsequent questions. It is important to understand the contents thoroughly before moving forward as the questions are closely related to the provided material.
Here the the automatically generated test suite for the CUT.
describe("AnonymousClass", () => {
it("throws an error when itemName is null", async () => {
const anonymousInstance = new AnonymousClass();
const itemName = null;
const quantity = 6;
try {
await anonymousInstance.removeItem(itemName, quantity);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("throws an error when discount is boolean", async () => {
const anonymousInstance = new AnonymousClass();
const discount = false;
try {
await anonymousInstance.applyDiscount(discount);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("throws an error when itemName is boolean and quantity is negative", async () => {
const anonymousInstance = new AnonymousClass();
const itemName = false;
const quantity = -4.463676586368846;
try {
await anonymousInstance.removeItem(itemName, quantity);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("calls getTotalPrice and returns 0", async () => {
const anonymousInstance = new AnonymousClass();
const returnValue = await anonymousInstance.getTotalPrice();
expect(returnValue).to.equal(0);
});
it("calls getItem and returns undefined", async () => {
const anonymousInstance = new AnonymousClass();
const itemName = "f7TRlPDk8rN_1QhwDGbjrD0RS";
const returnValue = await anonymousInstance.getItem(itemName);
expect(returnValue).to.equal(undefined);
});
it("throws an error when itemName is boolean", async () => {
const anonymousInstance = new AnonymousClass();
const itemName = true;
const quantity = 5;
try {
await anonymousInstance.removeItem(itemName, quantity);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("throws an error when itemName is function", async () => {
const anonymousInstance = new AnonymousClass();
const itemName = () => {};
try {
const returnValue = await anonymousInstance.findItem(itemName);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("throws an error when itemName is positve, quantity is string, and price is string", async () => {
const anonymousInstance = new AnonymousClass();
const itemName = 9;
const quantity = " ";
const price = "QAvFGJhRb7V89b";
try {
await anonymousInstance.addItem(itemName, quantity, price);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("calls getItems and returns empty array", async () => {
const anonymousInstance = new AnonymousClass();
const returnValue = await anonymousInstance.getItems();
expect(JSON.parse(JSON.stringify(returnValue))).to.deep.equal([]);
});
it("throws an error when itemName is array", async () => {
const anonymousInstance = new AnonymousClass();
const itemName = ["FLxn4T3hFmo_pdwa"];
try {
const returnValue = await anonymousInstance.getItem(itemName);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("calls getTotalPrice and returns 0", async () => {
const anonymousInstance = new AnonymousClass();
const returnValue = await anonymousInstance.getTotalPrice();
expect(returnValue).to.equal(0);
});
it("calls clearCart and return an object", async () => {
const anonymousInstance = new AnonymousClass();
await anonymousInstance.clearCart();
expect(JSON.parse(JSON.stringify(anonymousInstance))).to.deep.equal({
items: [],
});
});
it("throws an error when itemName is number", async () => {
const anonymousInstance = new AnonymousClass();
const itemName = 2;
const quantity = 1;
const price = 3;
try {
await anonymousInstance.addItem(itemName, quantity, price);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("throws an error when quantity is string and price is negative", async () => {
const anonymousInstance = new AnonymousClass();
const itemName = "kzExxpeYXazeWf9mt1jS-lYsz_VLg";
const quantity = "3bBWPprqh6-UQhXbeB3JDd3ZjZlxM";
const price = -9;
try {
await anonymousInstance.addItem(itemName, quantity, price);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("calls getItemCount after clearCart and returns 0", async () => {
const anonymousInstance = new AnonymousClass();
await anonymousInstance.clearCart();
const returnValue = await anonymousInstance.getItemCount();
expect(returnValue).to.equal(0);
});
it("throws an error when price is negative", async () => {
const anonymousInstance = new AnonymousClass();
const itemName = "eyAo";
const quantity = 3;
const price = -5;
try {
const returnValue = await anonymousInstance.validateInput(
itemName,
quantity,
price
);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("calls findItem after addItem and returns undefined", async () => {
const anonymousInstance = new AnonymousClass();
const itemName1 = " ";
const quantity = 8;
const price = 3;
await anonymousInstance.addItem(itemName1, quantity, price);
const itemName2 = "wzjojDV1";
const returnValue2 = await anonymousInstance.findItem(itemName2);
expect(returnValue2).to.equal(undefined);
});
it("throws an error when existingItem is null", async () => {
const anonymousInstance = new AnonymousClass();
const itemName = "1q_r-l5U";
const quantity = 9;
try {
await anonymousInstance.removeItem(itemName, quantity);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("calls applyDiscount and returns an object", async () => {
const anonymousInstance = new AnonymousClass();
const discount = 0.8899157137301756;
await anonymousInstance.applyDiscount(discount);
expect(JSON.parse(JSON.stringify(anonymousInstance))).to.deep.equal({
items: [],
});
});
it("throws an error when itemName is boolean, quantity is negative, and price is string", async () => {
const anonymousInstance = new AnonymousClass();
const itemName = true;
const quantity = -5;
const price = "rLq8PuPerUGBxu-Eun0OqMbNU";
try {
await anonymousInstance.addItem(itemName, quantity, price);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("calls getItem after addItem and returns undefined", async () => {
const anonymousInstance = new AnonymousClass();
const itemName1 = "pvl3A6SYojiN3mtY-cRXQfm5!93";
const quantity = 1;
const price = 9.956023066500322;
await anonymousInstance.addItem(itemName1, quantity, price);
const itemName2 = "VNVsx7";
const returnValue = await anonymousInstance.getItem(itemName2);
expect(returnValue).to.equal(undefined);
});
});
Class Name [ _______________________ ]
Based on your understanding from the test suite, can you identify any specific inputs or scenarios where the removeItem and addItem might throw an exception? Select the answer that you think is appropriate.
Here we provide the source code of the addItem and removeItem.
Please read the following code and answer the related questions.
addItem(itemName, quantity, price) {
this.validateInput(itemName, quantity, price);
const existingItem = this.findItem(itemName);
if (existingItem) {
existingItem.quantity += quantity;
} else {
this.items.push(new ShoppingCartItem(itemName, quantity, price));
}
return this;
}
removeItem(itemName, quantity) {
this.validateInput(itemName, quantity, 0);
const existingItem = this.findItem(itemName);
if (!existingItem) {
throw new Error("Item does not exist");
}
if (existingItem.quantity < quantity) {
throw new Error("Invalid quantity");
} else if (existingItem.quantity === quantity) {
this.items = this.items.filter((item) => item.productName !== itemName);
} else {
existingItem.quantity -= quantity;
}
return this;
}
validateInput(itemName, quantity, price) {
const errors = [];
if (typeof itemName !== "string" || itemName.length === 0) {
errors.push("Invalid item name");
}
if (typeof quantity !== "number" || quantity < 0) {
errors.push("Invalid quantity");
}
if (typeof price !== "number" || price < 0) {
errors.push("Invalid price");
}
if (errors.length > 0) {
throw new Error(errors.join(", "));
}
}
findItem(itemName) {
if (typeof itemName !== "string" || itemName.length === 0) {
throw new Error("Invalid item name");
}
return this.items.find((item) => item.productName === itemName);
}
the test suite provided earlier effectively serves as “live” documentation that helps you understand these two methods better.
it was easy for you to understand the functionality and design of the AnonymousClass from the test suite
you were confident in your understanding of the AnonymousClass based on the test suite
Please elaborate on your answer *
We value your insights and would like to offer you an optional opportunity to earn additional rewards. By choosing to complete one more task following, you will receive extra reward.
In this task, we will provide you with a set of automatically generated test cases. Your task is to review these test cases and group them into different categories. This process is known as ‘test case clustering’.
You need to categorize these test cases based on your own idea, such as the functionality they test, the methods they use, the input data they require, or any other criteria that make sense to you. We encourage you to create clusters that help you understand the test suite and the underlying code better.
After you finish the clustering, we will ask you to provide a brief justification for your categorization. This is to help us understand your thought process and the logic behind your decisions.
Here are all the test cases you will use in this task, you can go to the question part first and review the code as you need.
Find the class under test here.
it("TC1: throws an error when itemName is null", async () => {
const shoppingCart = new ShoppingCart();
const itemName = null;
const quantity = 6;
try {
await shoppingCart.removeItem(itemName, quantity);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("TC2: throws an error when discount is boolean", async () => {
const shoppingCart = new ShoppingCart();
const discount = false;
try {
await shoppingCart.applyDiscount(discount);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("TC3: throws an error when itemName is boolean and quantity is negative", async () => {
const shoppingCart = new ShoppingCart();
const itemName = false;
const quantity = -4.463676586368846;
try {
await shoppingCart.removeItem(itemName, quantity);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("TC4: calls getTotalPrice and returns 0", async () => {
const shoppingCart = new ShoppingCart();
const returnValue = await shoppingCart.getTotalPrice();
expect(returnValue).to.equal(0);
});
it("TC5: calls getItem and returns undefined", async () => {
const shoppingCart = new ShoppingCart();
const itemName = "f7TRlPDk8rN_1QhwDGbjrD0RS";
const returnValue = await shoppingCart.getItem(itemName);
expect(returnValue).to.equal(undefined);
});
it("TC6: throws an error when itemName is boolean", async () => {
const shoppingCart = new ShoppingCart();
const itemName = true;
const quantity = 5;
try {
await shoppingCart.removeItem(itemName, quantity);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("TC7: throws an error when itemName is function", async () => {
const shoppingCart = new ShoppingCart();
const itemName = () => {};
try {
const returnValue = await shoppingCart.findItem(itemName);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("TC8: throws an error when itemName is positve, quantity is string, and price is string", async () => {
const shoppingCart = new ShoppingCart();
const itemName = 9;
const quantity = " ";
const price = "QAvFGJhRb7V89b";
try {
await shoppingCart.addItem(itemName, quantity, price);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("TC9: calls getItems and returns empty array", async () => {
const shoppingCart = new ShoppingCart();
const returnValue = await shoppingCart.getItems();
expect(JSON.parse(JSON.stringify(returnValue))).to.deep.equal([]);
});
it("TC10: throws an error when itemName is array", async () => {
const shoppingCart = new ShoppingCart();
const itemName = ["FLxn4T3hFmo_pdwa"];
try {
const returnValue = await shoppingCart.getItem(itemName);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("TC11: calls getTotalPrice and returns 0", async () => {
const shoppingCart = new ShoppingCart();
const returnValue = await shoppingCart.getTotalPrice();
expect(returnValue).to.equal(0);
});
it("TC12: calls clearCart and return an object", async () => {
const shoppingCart = new ShoppingCart();
await shoppingCart.clearCart();
expect(JSON.parse(JSON.stringify(shoppingCart))).to.deep.equal({
items: [],
});
});
it("TC13: throws an error when itemName is number", async () => {
const shoppingCart = new ShoppingCart();
const itemName = 2;
const quantity = 1;
const price = 3;
try {
await shoppingCart.addItem(itemName, quantity, price);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("TC14: throws an error when quantity is string and price is negative", async () => {
const shoppingCart = new ShoppingCart();
const itemName = "kzExxpeYXazeWf9mt1jS-lYsz_VLg";
const quantity = "3bBWPprqh6-UQhXbeB3JDd3ZjZlxM";
const price = -9;
try {
await shoppingCart.addItem(itemName, quantity, price);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("TC15: calls getItemCount after clearCart and returns 0", async () => {
const shoppingCart = new ShoppingCart();
await shoppingCart.clearCart();
const returnValue = await shoppingCart.getItemCount();
expect(returnValue).to.equal(0);
});
it("TC16: throws an error when price is negative", async () => {
const shoppingCart = new ShoppingCart();
const itemName = "eyAo";
const quantity = 3;
const price = -5;
try {
const returnValue = await shoppingCart.validateInput(
itemName,
quantity,
price
);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("TC17: calls findItem after addItem and returns undefined", async () => {
const shoppingCart = new ShoppingCart();
const itemName1 = " ";
const quantity = 8;
const price = 3;
await shoppingCart.addItem(itemName1, quantity, price);
const itemName2 = "wzjojDV1";
const returnValue2 = await shoppingCart.findItem(itemName2);
expect(returnValue2).to.equal(undefined);
});
it("TC18: throws an error when existingItem is null", async () => {
const shoppingCart = new ShoppingCart();
const itemName = "1q_r-l5U";
const quantity = 9;
try {
await shoppingCart.removeItem(itemName, quantity);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("TC19: calls applyDiscount and returns an object", async () => {
const shoppingCart = new ShoppingCart();
const discount = 0.8899157137301756;
await shoppingCart.applyDiscount(discount);
expect(JSON.parse(JSON.stringify(shoppingCart))).to.deep.equal({
items: [],
});
});
it("TC20: throws an error when itemName is boolean, quantity is negative, and price is string", async () => {
const shoppingCart = new ShoppingCart();
const itemName = true;
const quantity = -5;
const price = "rLq8PuPerUGBxu-Eun0OqMbNU";
try {
await shoppingCart.addItem(itemName, quantity, price);
} catch (e) {
expect(e).to.be.an("error");
}
});
it("TC21: calls getItem after addItem and returns undefined", async () => {
const shoppingCart = new ShoppingCart();
const itemName1 = "pvl3A6SYojiN3mtY-cRXQfm5!93";
const quantity = 1;
const price = 9.956023066500322;
await shoppingCart.addItem(itemName1, quantity, price);
const itemName2 = "VNVsx7";
const returnValue = await shoppingCart.getItem(itemName2);
expect(returnValue).to.equal(undefined);
});
Please remember, there are no ‘right’ or ‘wrong’ answers in this task. We are interested in your personal approach to understanding test cases and how you perceive their organization can aid in comprehension.
(tip: you can review the categoried image by zooming in or out on the webpage, the image retains its original resolution) *
Drag items from below into the appropriate categories.
[____________________]
Drop an item here to create a new category
[____________________]
16. Please provide a simple explanation of your rules of categorizing. *
Thank you for taking our survey. Your response is very important to us.
测试需要分为基础测试和功能测试,基础测试保证程序运行下去,功能测试保证程序结果是理想的
摘录自一次问卷调查,为防原地址失效特记录于此,英文好的小伙伴可以过一遍,相信对前端单元测试的理解会有所帮助
over。。。